2010-09-21 110 views
0

今天看了一下形式佈局關於Flex的表格佈局問題

<mx:Form id="form"> 
     <mx:FormItem label="horizontal:"> 
      <mx:Text text="test"/> 
     </mx:FormItem> 
</mx:Form> 

給出了格式「標籤」輸出 - 「文本框」。但我想更改方向而不更改代碼。像

標籤

複選框

我怎樣才能做到這一點。請詳細解釋。

感謝和問候,

KARTHIK亞拉曼

回答

0

我認爲你必須重寫的FormItem代碼,並改變它定位它的孩子的方式。

我懷疑這是微不足道的,但我不希望它很難。打開表單代碼並查看updateDisplayList()。

0

你舉的例子不是很清楚,但使用下面的例子也許會澄清你問

<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>

0

我已經做到了這一點,標籤垂直在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(); 
     } 
    } 
} 

}