创建适用于Flex移动应用的ComboBox (下拉菜单) 控件
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,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,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"/> |
运行结果如图:
Flex DataGrid/AdvancedDatagrid 性能优化技巧(1) — ItemRenderer《ActionScript 3.0 基础教程》
57 Responses to “创建适用于Flex移动应用的ComboBox (下拉菜单) 控件”
转自:http://www.flextheworld.com/2011/08/flex-mobile-combobox.html
flex 高手系列参考资料