Вопрос по макету формы во Flex - PullRequest
0 голосов
/ 21 сентября 2010

Сегодня посмотрел на макет формы

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

дает вывод в формате «метка» - «текстовое поле». Но я хочу изменить ориентацию без изменения кода. Как

метка

Флажок

Как я могу это сделать. Пожалуйста, объясните подробно.

Спасибо и всего наилучшего,

Картик Джаяраман

Ответы [ 3 ]

0 голосов
/ 21 сентября 2010

Ваш пример не очень понятен, но, используя приведенные ниже примеры, возможно, он прояснит то, что вы спрашиваете

    <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 голосов
/ 22 сентября 2010

Я сделал это с надписью вертикально над элементом формы в Flex 3, и это было не красиво.Это работало, но не было самым стабильным и требовало серьезного взлома методов жизненного цикла компонентов.

В Flex 4 новая модель скинов исправляет это, используйте, если это возможно, выходящий в выпуске Hero (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();
        }
    }
}

}

0 голосов
/ 21 сентября 2010

Я думаю, вам придется переопределить код formItem и изменить его положение для дочерних.

Я сомневаюсь, что это тривиально, но я не ожидаю, что это будет сложно.Откройте код формы и просмотрите updateDisplayList ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...