flex:可编辑标签组件

时间:2011-09-21 04:47:08

标签: flex flex4

我正在尝试在flex4中创建一个可编辑的标签。

要做到这一点,我正在扩展textfield类,因此它包含一个标签控件元素。但是,一旦文本字段变得不可见,我就无法看到标签。

代码看起来像这样:

package unimap.components
{
import spark.components.Label;
import spark.components.TextInput;

public class SmartTextInput extends TextInput
{
    private var _label:Label;
    public function SmartTextInput()
    {
        super();
    }

    public override function set editable(value:Boolean):void
    {
        super.editable = value;

        if (value == false)
        {
            _label = new Label();
            _label.x = this.x;
            _label.y = this.y;
            _label.width = this.width;
            _label.height = this.height;
            _label.text = "Home";

            addChild( _label ); // This lines fail the code with error
                                                // Error: addChild() is not available in this class. Instead, use addElement() or modify //the skin, if you have one.

        }

        super.visible = false;
        trace("Editable")
    }
}

}

但如果我将addChild更改为addElement,我将看到以下错误: 1180:调用可能未定义的方法addElement。

有人可以建议我做错了什么吗?

3 个答案:

答案 0 :(得分:5)

这是我在生产系统中使用的解决方案:

package com.npacemo.component
{
    import flash.events.Event;
    import flash.events.FocusEvent;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.ui.Keyboard;

    import mx.core.UIComponent;

    import spark.components.Label;
    import spark.components.PopUpAnchor;
    import spark.components.TextInput;
    import spark.components.supportClasses.SkinnableComponent;

    [Event(name="change", type="flash.events.Event")]
    public class EditableLabel extends SkinnableComponent
    {
        [SkinState("normal")]
        [SkinState("selected")]
        [SkinPart(required="true")]
        public var labelComponent:Label;
        [SkinPart(required="true")]
        public var inputAnchor:PopUpAnchor;
        [SkinPart(required="true")]
        public var inputComponent:UIComponent;

        [Bindable]
        public var text:String; 

        public function EditableLabel()
        {
            addEventListener(MouseEvent.CLICK, handleDisplayLabelClick);
        }

        override protected function partAdded(partName:String, instance:Object):void
        {
            if (instance == labelComponent)
            {
                labelComponent.addEventListener(MouseEvent.CLICK, handleDisplayLabelClick);
            }
            else if (instance == inputComponent)
            {
                inputComponent.addEventListener(Event.CHANGE, handleInputComponentChange);
                inputComponent.addEventListener(KeyboardEvent.KEY_DOWN, handleTextInputKeyDown);
                inputComponent.addEventListener(FocusEvent.FOCUS_OUT, handleInputComponentFocusOut);
            }
        }

        private function handleInputComponentChange(e:Event):void
        {
            text = (inputComponent as TextInput).text;
            dispatchEvent(e.clone());
        }

        private function handleDisplayLabelClick(event:MouseEvent):void
        {
            skin.currentState = "selected";
            stage.addEventListener(MouseEvent.CLICK, handleStageClick);
        }

        private function handleStageClick(e:MouseEvent):void
        {
            if (!inputComponent.hitTestPoint(stage.mouseX, stage.mouseY))
            {
                stage.removeEventListener(MouseEvent.CLICK, handleStageClick);
                skin.currentState = "normal";
            }
        }

        private function handleTextInputKeyDown(event:KeyboardEvent):void
        {
            if (event.charCode == Keyboard.ENTER)
            {
                stage.removeEventListener(MouseEvent.CLICK, handleStageClick);
                skin.currentState = "normal";   
            }
        }

        private function handleInputComponentFocusOut(event:FocusEvent):void
        {
            stage.removeEventListener(MouseEvent.CLICK, handleStageClick);
            skin.currentState = "normal";
        }
    }
}

这是一个样本皮肤组件:

<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark" 
        xmlns:mx="library://ns.adobe.com/flex/mx">
    <!-- host component -->
    <fx:Metadata>
        [HostComponent("com.npacemo.component.EditableLabel")]
    </fx:Metadata>

    <!-- SkinParts
    name=inputComponent, type=mx.core.UIComponent, required=true
    name=labelComponent, type=spark.components.Label, required=true
    -->
    <s:states>
        <s:State name="normal"/>
        <s:State name="selected" enterState="inputComponent.setFocus(); inputComponent.selectRange(inputComponent.text.length, inputComponent.text.length);"/> 
    </s:states>

    <s:transitions>
        <s:Transition fromState="*" toState="*" autoReverse="true">
            <s:Fade targets="{[labelComponent, inputComponent]}" duration="100"/>
        </s:Transition>
    </s:transitions>

    <s:PopUpAnchor id="inputAnchor" x="-1" y="-7" displayPopUp.normal="false" displayPopUp.selected="true">
        <s:TextInput id="inputComponent" text="{hostComponent.text}" 
                     alpha.normal="0" alpha.selected="1" 
                     enabled.normal="false" enabled.selected="true"
                     width="{labelComponent.width + 20}" focusSkin="{null}" 
                     contentBackgroundColor="0xFBFCA4" borderVisible="false"
                     fontFamily="Futura" fontSize="12" textAlign="left">
            <s:filters>
                <s:DropShadowFilter angle="135" alpha="0.5" blurX="10" blurY="10"/>
            </s:filters>
        </s:TextInput>
    </s:PopUpAnchor>

    <s:Label id="labelComponent" text="{hostComponent.text}"
             alpha.normal="1" alpha.selected="0" 
             visible.normal="true" visible.selected="false"
             verticalCenter="0" width="{this.width+20}" maxDisplayedLines="1"
             textDecoration="underline" buttonMode="true"/>
</s:Skin>

答案 1 :(得分:0)

这里有一些问题。一,如果我多次调用enabled = false,我将会有多个标签子项。不是你想要的。您可以基于Group控件构建复合控件并创建自定义外观,但这可能有点过分。我建议只是为TextInput设置外观,并在未启用时将外观更改为看起来像标签(例如,背景和边框上的visible.disabled = false以及主要外观元素上的alpha.disabled = 1.0)这样做的好处是你可以通过CSS应用它并使用默认控件。

答案 2 :(得分:0)

基本上,TextInput不是一个Container,它是一个文本控件组件,因此你不能将子元素添加到它(使用addElement或addChild方法)。

您可以为TextInput创建一个外观,使TextInput“表现”为标签。

告诉我们您对“可编辑标签”的处理方式,这将使我们能够为您提供更好的答案。