Flex自带的comboBox也可以支持搜索,但是它是从第一位严格匹配的,如果我想做一个这样条件的搜索:只要lable中有输入的字符,那么就定位到匹配的第一个项。自定义itemMatchingFunction并不会允许客户输入一个字符串,而是当客户输入第一个字符串就立刻匹配并定位,显然这不是我们想要的。
唉,还是上代码吧。
App:
<?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:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:view="com.view.*"> <fx:Declarations> <!-- Place non-visual elements (e.g., services, value objects) here --> </fx:Declarations> <fx:Script> <![CDATA[ import mx.collections.ArrayCollection; import mx.collections.ArrayList; import spark.components.ComboBox; import spark.events.IndexChangeEvent; [Bindable] public var complexDP:ArrayCollection = new ArrayCollection( [ {ingredient:"Salmon", category:"Meat"}, {ingredient:"Potato", category:"Starch"}, {ingredient:"Cucumber", category:"Vegetable"}, {ingredient:"Steak", category:"Meat"}, {ingredient:"Rice", category:"Starch"}, {ingredient:"Cumin", category:"Spice"} ] ); ]]> </fx:Script> <s:layout> <s:VerticalLayout/> </s:layout> <view:ComboBoxSearch id="bcc" dataProvider="{complexDP}" width="150" selectedIndex="0" labelField="ingredient"/> </s:Application>
?ComboBoxSearch:
package com.view { import flash.events.Event; import flash.events.TimerEvent; import flash.utils.Timer; import flashx.textLayout.operations.CutOperation; import flashx.textLayout.operations.DeleteTextOperation; import flashx.textLayout.operations.FlowOperation; import flashx.textLayout.operations.InsertTextOperation; import mx.core.mx_internal; import org.osmf.events.TimeEvent; import spark.components.ComboBox; import spark.events.DropDownEvent; import spark.events.TextOperationEvent; public class ComboBoxSearch extends ComboBox { private var timer:Timer; private var tempEvent:TextOperationEvent; public function ComboBoxSearch() { super(); this.addEventListener(Event.ADDED_TO_STAGE,onAddToStageHandler); this.addEventListener(Event.REMOVED_FROM_STAGE,onRemoveToStageHandler); } private function onAddToStageHandler(event:Event):void { timer = new Timer(300,1); timer.addEventListener(TimerEvent.TIMER,onTimerHandler); } private function onRemoveToStageHandler(event:Event):void { if(timer.running) { timer.stop(); } timer.removeEventListener(TimerEvent.TIMER,onTimerHandler); timer = null; } override protected function textInput_changeHandler(event:TextOperationEvent):void { tempEvent = event; if(timer.running) { timer.stop(); } timer.reset(); timer.start(); } private function onTimerHandler(event1:TimerEvent):void { var operation:FlowOperation = tempEvent.operation; if (operation is DeleteTextOperation || operation is CutOperation) { super.mx_internal::changeHighlightedSelection(CUSTOM_SELECTED_ITEM); processInputField(); } else { if (openOnInput) { if (!isDropDownOpen) { openDropDown(); addEventListener(DropDownEvent.OPEN, editingOpenHandler); return; } } processInputField(); } } private function editingOpenHandler(event:DropDownEvent):void { removeEventListener(DropDownEvent.OPEN, editingOpenHandler); processInputField(); } private function processInputField():void { var matchingItems:Vector.<int>; if (!dataProvider || dataProvider.length <= 0) return; if (textInput.text != "") { if (itemMatchingFunction != null) matchingItems = itemMatchingFunction(this, textInput.text); else matchingItems = findMatchingItems(textInput.text); if (matchingItems.length > 0) { super.mx_internal::changeHighlightedSelection(matchingItems[0], true); var typedLength:int = textInput.text.length; var item:Object = dataProvider ? dataProvider.getItemAt(matchingItems[0]) : undefined; if (item) { var itemString:String = itemToLabel(item); textInput.selectAll(); textInput.insertText(itemString); textInput.selectRange(typedLength, itemString.length); } } else { super.mx_internal::changeHighlightedSelection(CUSTOM_SELECTED_ITEM); } } else { super.mx_internal::changeHighlightedSelection(NO_SELECTION); } } private function findMatchingItems(input:String):Vector.<int> { var startIndex:int; var stopIndex:int; var retVal:int; var retVector:Vector.<int> = new Vector.<int>; retVal = findStringLoop(input, 0, dataProvider.length); if (retVal != -1) retVector.push(retVal); return retVector; } private function findStringLoop(str:String, startIndex:int, stopIndex:int):Number { for (startIndex; startIndex != stopIndex; startIndex++) { var itmStr:String = itemToLabel(dataProvider.getItemAt(startIndex)); if(itmStr) { if(itmStr.toLowerCase().indexOf(str.toLowerCase()) > -1) { return startIndex; } } } return 0; } } }
?当然,如果你想优化搜索的方法,那么就你只要修改findStringLoop方法即可。
?
?