创建适用于Flex移动应用的ComboBox (下拉菜单) 控件
2011/08/05 Kevin Luo Flex 迷你教程, 开源控件,
Flex 4.5 已经发布一段时间了,它针对移动设备提供了大量优化过的组建。但是不知道为什么,忽略了ComboBox (下拉菜单)这个在传统Flex项目中出境率超高的组件。ios的SDK中也没有这个组建,好吧。我承认comboBox也许不符合apple定义的“移动设备操作规范”。但是咱的客户就爱使用ComboxBox. 咱就是要尽量保持移动设备应用与桌面应用风格保持一致。怎么办呢?
没有咱就造一个吧,首先问了万能的google. 别说还被我找到一个 《Hacking Flex 4.5 SDK add some ComboBox to Mobile development》http://www.igorcosta.org/?p=360,证明不止我一个人有这需求。
但是经过试用之后,发现一些问题,影响还比较大
1. 不能设置宽度,高度.
2. 控件不会根据设备自适应大小。
3. 选中值以后,Label没有及时更新
4. 略显简陋。
5. 有一些我想要修改的部分。
决定在他代码的基础上动手完善它,基于开源代码大家享的原则,文章最后我附上了我修改的版本。
而写这篇文章的是因为这是非常好的Flex 4.5自定义控件的例子,展示了如何通过Spark构架的Skin模块,创建任意外观但共享逻辑代码的控件。
这个ComboBox控件由3部分组成
逻辑部分:
ButtonBox.mxml (下拉菜单按钮)
ButtonBoxImpl.mxml (下拉菜单弹出的List)
Skin部分:
ButtomBoxSkin.mxml (下拉菜单按钮皮肤)
ButtonBoxSkinImpl.mxml (弹出List皮肤)
Event部分:
ButtonBoxEvent (下拉菜单相关事件,如OPENED,CHANGED)
咱们一起来看看重点部分的代码
ButtonBox.mxml
......
//Skin部分需要声明的对象,required = ture表示Skin必须声明该对象,我们使用这个对象来显示选中的值
[SkinPart(required="true")]
public var promptDisplay:Label;
......
//CreationComplete时设置属性和控件布局,默认prompt是Touch to select
protected function init(event:FlexEvent):void
{
label = _prompt;
invalidateProperties();
invalidateDisplayList();
}
//下拉菜单显示默认值
override protected function commitProperties():void
{
super.commitProperties();
promptDisplay.text = label;
}
//点击下拉菜单时弹出List。
protected function openList():void
{
list = new ButtonBoxImpl();
list.open(this,true);
list.x = (screen.width - list.width)/2;
list.y = (screen.height - list.height)/2;
list._title.text = _prompt;
list.dataProvider = _dp;
list.addEventListener(IndexChangeEvent.CHANGE,selectionHandler,true,1,true);
dispatchEvent(new ButtonBoxEvent(ButtonBoxEvent.OPENED,true));
}
//选中item后响应,显示选中的值,发出Selected事件
protected function selectionHandler(event:IndexChangeEvent):void
{
_selected = list.selectedItem;
_selectedIndex = list.selectedIndex;
label = String(list._optionsList.selectedItem.label);
invalidateProperties()
dispatchEvent(new ButtonBoxEvent(ButtonBoxEvent.SELECTED,true));
list.close();
list = null;
} |
ButtonBoxSkin.mxml
整个下拉菜单的按钮都是绘制出来的,Skin的绘制可以非常灵活,我们只需要在Skin中保证逻辑代码中申明的promptDisplay对象存在,其他的一切都可以任意改变。我们这里绘制了一个标准ComboBox框的样子。

<?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" minWidth="200" minHeight="44">
<!-- host component -->
<fx:Metadata>
[HostComponent("common.widgets.buttonbox.ButtonBox")]
</fx:Metadata>
<!-- states -->
<s:states>
<s:State name="disabled" />
<s:State name="down" />
<s:State name="over" />
<s:State name="up" />
</s:states>
<s:Rect width="100%" height="100%">
<s:stroke>
<s:SolidColorStroke caps="none" color="#5C5C5C" joints="miter" miterLimit="4"
weight="1"/>
</s:stroke>
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry alpha="1" color="#FFFFFF" ratio="0"/>
<s:GradientEntry alpha="1.0" color="#CCCCCC" ratio="1"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Group width="17.5%" height="100%" right="0">
<s:Rect width="100%" height="100%" >
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry alpha="1.0" color="#999999" ratio="0"/>
<s:GradientEntry alpha="1.0" color="#333333" ratio="1"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Path data="M 17.08 0.03 L 8.55 14.80 0.02 0.03 Z "
horizontalCenter="0" verticalCenter="0">
<s:fill>
<s:SolidColor color="#000000"/>
</s:fill>
</s:Path>
</s:Group>
<s:Label width="82%" id="promptDisplay" left="6" top="12" color="#464646" fontStyle="italic"
text="Prompt Text">
</s:Label>
</s:Skin> |
ButtonBoxImpl.mxml
这个文件里是弹出的List的逻辑代码部分,SkinPart的对象是_title和_optionsList.分辨是弹出时的提示语,如Touch to select以及一个List控件。监听了_optionsList。的选择事件在setField方法里相应。设置selectedIndex,以及selectedItem. 以上就是下拉弹出菜单全部需要的逻辑了。
ButtonBoxSkinImpl.mxml
和前面ButtonBoxSKin类似,除了必须要有的对象_title和_optionsList(当然还有宿主hostComponent)以外,其余的东西可以任意绘制,我们还是绘制一个带有背景阴影的List。大小随着设备大小自动适应。
ButtonBoxEvent.as
这个事件没有什么特别需要说明的,声明了一些自定义的事件,OPENED,CHANGED,CLOSED. 在适当的时候从ButtonBox里发出。
控件源代码:
ButtonBox (315)
使用方法
....
[Bindable]
private var languages:ArrayCollection=new ArrayCollection([{label: "English", value: "en_US"}, {label: "Spanish", value: "es_ES"}, {label: "French(BETA)", value: "fr_FR"}, {label: "German(BETA)", value: "de_DE"}, {label: "Ltalian(BETA)", value: "it_IT"}, {label: "Portuguese(BETA)", value: "pt_PT"}])
......
<buttonbox:ButtonBox width="200"
fontSize="18"
dataProvider="{languages}"
labelField="label"
prompt="Touch to select"/> |
运行结果如图:


combobox,flex 4.5, mobile
57 Responses to “创建适用于Flex移动应用的ComboBox (下拉菜单) 控件”
?
转自:http://www.flextheworld.com/2011/08/flex-mobile-combobox.html
?
flex 高手系列参考资料