今天看了一下形式佈局關於Flex的表格佈局問題
<mx:Form id="form">
<mx:FormItem label="horizontal:">
<mx:Text text="test"/>
</mx:FormItem>
</mx:Form>
給出了格式「標籤」輸出 - 「文本框」。但我想更改方向而不更改代碼。像
標籤
複選框
我怎樣才能做到這一點。請詳細解釋。
感謝和問候,
KARTHIK亞拉曼
今天看了一下形式佈局關於Flex的表格佈局問題
<mx:Form id="form">
<mx:FormItem label="horizontal:">
<mx:Text text="test"/>
</mx:FormItem>
</mx:Form>
給出了格式「標籤」輸出 - 「文本框」。但我想更改方向而不更改代碼。像
標籤
複選框
我怎樣才能做到這一點。請詳細解釋。
感謝和問候,
KARTHIK亞拉曼
我認爲你必須重寫的FormItem代碼,並改變它定位它的孩子的方式。
我懷疑這是微不足道的,但我不希望它很難。打開表單代碼並查看updateDisplayList()。
你舉的例子不是很清楚,但使用下面的例子也許會澄清你問
<mx:Form id="form">
<mx:FormItem label="Layout Demo:">
<mx:TextInput text="Input 1"/>
<mx:TextInput text="Input 2"/>
</mx:FormItem>
</mx:Form>
會呈現:
"Layout Demo: | Input 1 |"
| Input 2 |
如果你想改變它水平呈現爲:
"Layout Demo: | Input 1 | | Input 2 |"
將屬性direction="horizontal"
添加到<mx:FormItem>
我已經做到了這一點,標籤垂直在Flex 3中的表單項上方,並且它不漂亮。它的工作,但它不是最穩定,並需要嚴重的組件生命週期方法的黑客攻擊。
在Flex 4中,新的外觀模型修復了這個問題,如果可能,請使用英雄版本(http://blog.flexexamples.com/2010/08/28/creating-a-simple-spark-form-in-flex-hero/)。
以下是我在Flex 3中用於覆蓋的代碼的相關位,它是YMMV的一種方法。
NB該組件在它有更多的事情,我把東西出來,從而給出一個粗略的指南,我怎麼走近它,它可能無法運行,但也有一些調整它應該沒問題。
package my.controls
{
import flash.display.DisplayObject;
import mx.containers.FormItem;
import mx.containers.FormItemDirection;
import mx.core.EdgeMetrics;
import mx.core.IDeferredInstance;
import mx.core.UIComponent;
import mx.styles.CSSStyleDeclaration;
import mx.styles.StyleManager;
/**
* Allows positioning of the FormItem labels to be as inherited from FormItem, or
* allows for top alignment of labels whilst resizing form elements to fill width
* of parent container.
*
* <p>Possible values are: <code>left</code>; and <code>top</code>.</p>
* <p>Default value is: left.</p>
*/
[Style(name="labelAlign", type="String", enumeration="left,top", inherit="no")]
public class MyFormItem extends FormItem
{
private static const labelAlignStyleName:String = "labelAlign";
private static var classConstructed:Boolean = constructCustomStyle();
private var _isFormItemLabelTopAligned:Boolean;
private var _hasFormItemLabel:Boolean;
/**
* This calls the super.commitProperties() method and then sets instance variables
* indicating on whether the labels should be top aligned, and also if there is
* a non zero length string as the label value.
*/
override protected function commitProperties():void
{
super.commitProperties();
if (label != null && label.length > 0)
{
_hasFormItemLabel = true;
}
if (getStyle(labelAlignStyleName) == "top")
{
_isFormItemLabelTopAligned = true;
}
}
/**
* After calling the super.measure() method, a check is made to see if there is a label
* value, and if the label is top aligned. If so, it modifies the measuredHeight and
* measuredMinHeight to include the height of the label, plus the indicatorGap style value
*/
override protected function measure():void
{
super.measure();
//If this is top aligned, then change the height of this component
if (_isFormItemLabelTopAligned)
{
if (_hasFormItemLabel)
{
var addedHeight:Number = itemLabel.getExplicitOrMeasuredHeight() + getStyle(indicatorGapStyleName);
//Add the height of the label
measuredHeight = measuredHeight + addedHeight;
measuredMinHeight = measuredMinHeight + addedHeight;
}
//Ignore any measured width we may get, caclulate the width as being the greater of the label or child
var children:Array = getChildren();
var maxChildWidth:Number = 0;
//Usually there is only 1 child, but code for in case there are more
for each (var child:DisplayObject in children)
{
var uiComp:UIComponent = child as UIComponent;
maxChildWidth = Math.max(maxChildWidth, uiComp.getExplicitOrMeasuredWidth());
}
//Set the measurement
measuredWidth = measuredMinWidth = Math.max(itemLabel.getExplicitOrMeasuredWidth(),
maxChildWidth);
}
}
/**
* <p>Checks for label top alignment and if so, changes the location of label to be
* moved to the top left of the container. It then proceeds to layout the children depending on
* whether the <code>MyFormItem.direction</code> property is horizontal or vertical.</p>
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if (_isFormItemLabelTopAligned)
{
//Anchor the label to the top left of the container
if (_hasFormItemLabel)
{
var vm:EdgeMetrics = viewMetricsAndPadding;
itemLabel.move(vm.left, vm.top);
}
//Depending on the layout of the MyFormItem items, take appropriate action
if (numChildren > 0)
{
if (direction == FormItemDirection.VERTICAL)
{
moveVerticalLayoutWithTopLabel();
}
else
{
moveHorizontalLayoutWithTopLabel();
}
}
findAndRemoveIndicator();
}
}
/**
* <p>Given that labelAlign is set to be top aligned, this method works out the new
* positioning and size of the vertically aligned children. It uses the <code>verticalGap</code>
* style property to set a width between the children.</p>
*/
protected function moveVerticalLayoutWithTopLabel():void
{
var vm:EdgeMetrics = viewMetricsAndPadding;
var commonX:Number = vm.left;
var child:UIComponent;
var previousChild:UIComponent = null;
var newY:Number = vm.top + (_hasFormItemLabel ? (itemLabel.getExplicitOrMeasuredHeight() + getStyle(indicatorGapStyleName)) : 0);
var availableWidth:Number = this.width - getStyle("paddingLeft") - getStyle("paddingRight");
for (var i:Number = 0; i < numChildren; i++)
{
//Calculate the new Y value of the child including the vertical gap
if (previousChild != null)
{
newY = newY + previousChild.getExplicitOrMeasuredHeight() + getStyle("verticalGap");
}
child = UIComponent(getChildAt(i));
child.move(commonX, newY);
//If these children are percentWidths, then set the size of them as we have more width now
if (!isNaN(child.percentWidth))
{
var childSize:Number = availableWidth * (child.percentWidth/100);
child.setActualSize(childSize, child.getExplicitOrMeasuredHeight());
}
previousChild = child;
}
}
/**
* <p>Given that labelAlign is set to be top aligned, this method works out the new
* positioning and size of the horizontal aligned children. It uses the <code>horizontalGap</code>
* style property to set a width between the children.</p>
*/
protected function moveHorizontalLayoutWithTopLabel():void
{
var child:UIComponent;
var previousChild:UIComponent = null;
var vm:EdgeMetrics = viewMetricsAndPadding;
var commonY:Number = vm.top + (_hasFormItemLabel ? (itemLabel.getExplicitOrMeasuredHeight() + getStyle(indicatorGapStyleName)) : 0);
var newX:Number = vm.left;
var availableWidth:Number = this.width - getStyle("paddingLeft") - getStyle("paddingRight");
for (var i:int = 0; i < numChildren; i++)
{
//Calculate the new X postion of the child taking into account of the label move
if (previousChild != null)
{
newX = newX + previousChild.width + getStyle("horizontalGap");
}
child = UIComponent(getChildAt(i));
child.move(newX, commonY);
//If these children are percentWidths, then set the size of them as we have more width now
if (!isNaN(child.percentWidth))
{
var childSize:Number = availableWidth * (child.percentWidth/100);
child.setActualSize(childSize, child.getExplicitOrMeasuredHeight());
}
previousChild = child;
}
}
private function findAndRemoveIndicator():void
{
if (!required)
{
return;
}
var indicatorClass:Class = getStyle("indicatorSkin") as Class;
var rawChildrenLength:int = rawChildren.numChildren;
for (var i:int = 0; i < rawChildrenLength; i++)
{
var displayObject:DisplayObject = rawChildren.getChildAt(i);
if (displayObject is indicatorClass)
{
rawChildren.removeChild(displayObject);
return;
}
}
}
/**
* A convenience method to register a style with the StyleManager and create the necessary
* defaults.
*/
private static function constructCustomStyle():Boolean
{
const className:String = "MyFormItem";
const defaultLabelAlignment:String = "left";
const defaultIndicatorGap:Number = 2;
if (!classConstructed)
{
var style:CSSStyleDeclaration = StyleManager.getStyleDeclaration(className);
if (style)
{
if (style.getStyle(labelAlignStyleName) == undefined)
{
style.setStyle(labelAlignStyleName, defaultLabelAlignment);
}
}
else
{
style = new CSSStyleDeclaration();
style.defaultFactory = function():void
{
this[labelAlignStyleName] = defaultLabelAlignment;
}
StyleManager.setStyleDeclaration(className, style, true);
}
}
return true;
}
/**
* Calls super.styleChanged() method.
*
* If the labelAlign style changes, then the component is invalidated as
* its properties and size recalculated as well as being redrawn.
*/
override public function styleChanged(styleProp:String):void
{
super.styleChanged(styleProp);
// Check to see if style changed.
if (styleProp == labelAlignStyleName)
{
invalidateProperties();
invalidateSize();
invalidateDisplayList();
}
}
}
}