【问题标题】:flex: Editable Label Componentflex:可编辑标签组件
【发布时间】:2011-09-21 04:47:07
【问题描述】:

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

为此,我扩展了文本字段类,因此它包含一个标签控制元素。但是,一旦文本字段变得不可见,我就无法使标签可见。

代码如下所示:

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。

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

【问题讨论】:

    标签: apache-flex flex4


    【解决方案1】:

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

    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>
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 你能写一个简短的例子吗?我觉得皮肤不是我真正需要的。因为有一次我需要在文本标签上画一个圆圈......所以这就是我决定制作自定义组件的原因。 (我不在乎有多少儿童标签 atm.... 只需要一个有效的机制)
      【解决方案3】:

      基本上,TextInput 不是一个容器,它是一个文本控件组件,因此您不能向其中添加子元素或元素(使用 addElement 或 addChild 方法)。

      您可以为您的 TextInput 创建一个皮肤,使您的 TextInput “表现”为标签。

      告诉我们你想用你的“可编辑标签”做什么,这将使我们能够给你一个更好的答案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-17
        • 1970-01-01
        • 2014-01-14
        • 1970-01-01
        相关资源
        最近更新 更多