我是flex的新手,正在构建一个flex 4.5应用程序,它有一个扩展SkinnableContainer的自定义组件。这个自定义组件基本上是一种可折叠的面板。当你打开它时,你会看到contentGroup中的所有控件,当你关闭它们时它们会消失,你就会得到标题。这是通过使contentGroup仅包含在打开状态而在皮肤中完成的。
我在应用程序中有一堆这样的容器,有些是默认打开的,有些是关闭的。 所以在mxml中结构如下:
<ui:MyCustomContainer open="false" label="bla">
<s:HGroup>
<s:Button />
<ui:AnotherComponent />
<etc />
</s:HGroup>
</ui:MyCustomContainer>
我的问题是我无法访问(通过动作脚本,例如在事件处理中)来自已关闭容器的组件(实际上它们的初始化事件代码不会运行),直到它们至少打开一次。
进行一些挖掘我发现flex在延迟创建组件方面有一些性能提升。因此,我认为这必须是我在SkinnableContainer上将creationPolicy设置为“all”的答案:
<ui:MyCustomContainer open="false" label="bla" creationPolicy="all" >
但这不起作用。有什么想法吗?
更新:以下完整示例
Revealer.as可换肤容器(摘自Flex 4 in Action并略微删除)
package
{
import flash.events.Event;
import spark.components.SkinnableContainer;
import spark.components.ToggleButton;
import spark.components.supportClasses.TextBase;
[SkinState("open")]
[SkinState("closed")]
[SkinState("disabled")] //Not used: just appeasing compiler in the skin when host component is defined.
[SkinState("normal")] //Not used: just appeasing compiler in the skin when host component is defined.
public class Revealer extends SkinnableContainer
{
private var m_open:Boolean = true;
private var m_label:String;
[SkinPart]
public var toggler:ToggleButton;
[SkinPart(required="false")]
public var labelDisplay:TextBase;
public function Revealer()
{
super();
}
public function get open():Boolean { return m_open; }
public function set open( value:Boolean ):void
{
if( m_open == value )
return;
m_open = value;
invalidateSkinState();
invalidateProperties();
}
public function get label():String { return m_label; }
public function set label( value:String ):void
{
if( m_label == value )
return;
m_label = value;
if( labelDisplay != null )
labelDisplay.text = value;
}
override protected function getCurrentSkinState():String { return m_open ? "open" : "closed"; }
override protected function partAdded( name:String, instance:Object ):void
{
super.partAdded( name, instance );
if(instance == toggler)
{
toggler.addEventListener( Event.CHANGE, toggleButtonChangeHandler );
toggler.selected = m_open;
}
else if( instance == labelDisplay )
{
labelDisplay.text = m_label;
}
}
private function toggleButtonChangeHandler( e:Event ):void
{
open = toggler.selected;
}
}
}
RevealerSkin.mxml容器的外观
<?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" >
<fx:Metadata>[HostComponent("Revealer")]</fx:Metadata>
<s:states>
<s:State name="open" />
<s:State name="closed" />
<s:State name="disabled" /> <!--not used: just appeasing compiler in the skin when host component is defined. -->
<s:State name="normal" /> <!--not used: just appeasing compiler in the skin when host component is defined. -->
</s:states>
<s:Rect radiusX="5" top="0" left="0" right="0" bottom="0" minWidth="200">
<s:stroke><s:SolidColorStroke weight="2" alpha="0.5"/></s:stroke>
</s:Rect>
<s:Group left="0" top="0" right="0" bottom="5">
<s:ToggleButton id="toggler" label="toggle" left="5" top="5" />
</s:Group>
<s:Label id="labelDisplay" left="{toggler.width + 10}" top="10" right="0" />
<s:Group id="contentGroup" includeIn="open" itemCreationPolicy="immediate" left="5" right="5" top="35" bottom="5" />
</s:Skin>
MyControl.mxml放置在容器内的自定义控件
<?xml version="1.0" encoding="utf-8"?>
<s:BorderContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
borderWeight="2" borderColor="black"
borderAlpha="0.2" cornerRadius="2"
height="25">
<fx:Script>
<![CDATA[
[Bindable] public var minVal:Number;
[Bindable] public var maxVal:Number;
[Bindable] public var defaultVal:Number;
public function get value():Number { return valueSlider.value; }
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:HGroup width="100%" paddingTop="5" paddingBottom="5" paddingLeft="5" paddingRight="5">
<s:Label text="Value:" />
<s:Spacer width="100%" />
<s:HSlider id="valueSlider" minimum="{minVal}" maximum="{maxVal}" value="{defaultVal}" />
</s:HGroup>
</s:BorderContainer>
RevealerTest.mxml用于演示问题的示例应用
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:local="*"
minWidth="955" minHeight="600" >
<fx:Script>
<![CDATA[
protected function onClick( e:MouseEvent ):void {
debugArea.text += control1.value + "\n" + control2.value + "\n";
}
]]>
</fx:Script>
<s:HGroup>
<s:VGroup>
<s:Button label="click me" click="onClick(event)" />
<local:Revealer label="Group 1" skinClass="RevealerSkin" creationPolicy="all">
<local:MyControl id="control1" minVal="0" maxVal="10" defaultVal="5"/>
</local:Revealer>
<local:Revealer label="Group 2" open="false" skinClass="RevealerSkin" creationPolicy="all">
<local:MyControl id="control2" minVal="0" maxVal="100" defaultVal="50"/>
</local:Revealer>
</s:VGroup>
<s:TextArea id="debugArea" />
</s:HGroup>
</s:Application>
请注意,如果在打开第二个容器之前点击“我”按钮,则无法从最初折叠的组中的控件获取值。打开组一次允许访问该值。折叠组仍然可以。这是第一次出现问题。我已将creationPolicy添加到容器中,并将itemCreationPolicy添加到皮肤中的内容组,但没有运气!
答案 0 :(得分:1)
实际上,这不是creationPolicy
您正在寻找itemCreationPolicy。这是隐藏元素(contentGroup)的属性。如果由于immediate
而未显示,则必须将其设置为currentState
才能访问元素事件。