flex AutoComplete 重写

flex AutoComplete 重写,继承combobox控件的重写

最终效果如下图:

代码如下:

所有文档结果如下:

AutoComplete.as代码如下:

package org.flashcommander.components
{

 import flash.events.FocusEvent;
 import flash.events.KeyboardEvent;
 import flash.events.MouseEvent;
 import flash.ui.Keyboard;
 import flash.ui.Mouse;
 import flash.ui.MouseCursor;
 
 import mx.collections.ArrayCollection;
 import mx.collections.ListCollectionView;
 import mx.collections.Sort;
 import mx.events.CollectionEvent;
 import mx.events.CollectionEventKind;
 import mx.events.FlexEvent;
 import mx.events.FlexMouseEvent;
 import mx.events.SandboxMouseEvent;
 
 import org.flashcommander.event.CustomEvent;
 
 import spark.components.Group;
 import spark.components.List;
 import spark.components.PopUpAnchor;
 import spark.components.TextInput;
 import spark.components.supportClasses.SkinnableComponent;
 import spark.events.TextOperationEvent;
 
 [Event (name="select", type="org.flashcommander.event.CustomEvent")]
 
 [Event (name="enter", type="mx.events.FlexEvent")]
 
 [Event (name="change", type="spark.events.TextOperationEvent")]

 public class AutoComplete extends SkinnableComponent
 {
  
  public function AutoComplete()
  {
   super();
   this.mouseEnabled = true;
   this.setStyle("skinClass", Class(AutoCompleteSkin));
   this.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut)
   collection.addEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChange)
   
  }
  
  public var maxRows:Number = 6;
  public var minChars:Number = 1;
  public var prefixOnly:Boolean = true;
  public var requireSelection:Boolean = false;
  
  [SkinPart(required="true",type="spark.components.Group")]
  public var dropDown:Group;
  [SkinPart(required="true",type="spark.components.PopUpAnchor")]
  public var popUp:PopUpAnchor;
  [SkinPart(required="true",type="spark.components.List")]
  public var list:List;
  [SkinPart(required="true",type="spark.components.TextInput")]
  public var inputTxt:TextInput;
  
  override protected function partAdded(partName:String, instance:Object) : void{
   super.partAdded(partName, instance)
   
   if (instance==inputTxt){
    inputTxt.addEventListener(FocusEvent.FOCUS_OUT, _focusOutHandler)
    inputTxt.addEventListener(FocusEvent.FOCUS_IN, _focusInHandler)
    inputTxt.addEventListener(TextOperationEvent.CHANGE, onChange);
    inputTxt.addEventListener("keyDown", onKeyDown);
    inputTxt.addEventListener(FlexEvent.ENTER, enter)
    inputTxt.text = _text;
   }
   if (instance==list){
    list.dataProvider = collection;
    list.labelField = labelField;
    list.labelFunction = labelFunction
    list.addEventListener(FlexEvent.CREATION_COMPLETE, addClickListener)
    list.focusEnabled = false;
    list.requireSelection = requireSelection
   }
   if (instance==dropDown){
    dropDown.addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, mouseOutsideHandler); 
    dropDown.addEventListener(FlexMouseEvent.MOUSE_WHEEL_OUTSIDE, mouseOutsideHandler);    
    dropDown.addEventListener(SandboxMouseEvent.MOUSE_DOWN_SOMEWHERE, mouseOutsideHandler);
    dropDown.addEventListener(SandboxMouseEvent.MOUSE_WHEEL_SOMEWHERE, mouseOutsideHandler);
   }
  }
  
  private var collection:ListCollectionView = new ArrayCollection();
  
  public function set dataProvider(value:Object){
   if (value is Array)
    collection = new ArrayCollection(value as Array);
   else if (value is ListCollectionView){
    collection = value as ListCollectionView;
    collection.addEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChange)
   }

   if (list) list.dataProvider = collection;
   
   filterData();
  }
  public function get dataProvider():Object { return collection; }
  
  private function collectionChange(event:CollectionEvent){
   if (event.kind == CollectionEventKind.RESET || event.kind == CollectionEventKind.ADD)
    filterData();
  }
  
  private var _text:String = "";
  
  public function set text(t:String){
   _text = t;
   if (inputTxt) inputTxt.text = t;
  }
  public function get text():String{
   return _text;
  }
  
  private var _labelField : String;
  public function set labelField(field:String) : void {
   _labelField = field;
   if (list) list.labelField = field
  }
  public function get labelField():String { return _labelField };
  
  public function set labelFunction(func:Function) : void {
   _labelFunction = func;
   if (list) list.labelFunction = func
  }
  public function get labelFunction() : Function { return _labelFunction; }
  
  private var _labelFunction:Function;
  
  public var returnField:String;
  
  public function get selectedItem() : Object { return _selectedItem; }
  
  public function set selectedItem(item:Object) {
   _selectedItem = item;
   //inputTxt.text = returnFunction(item);
   text = returnFunction(item)
  }
  
  private var _selectedItem:Object;
  
  public function get selectedIndex() : int { return _selectedIndex; }
  private var _selectedIndex : int = -1;
  
  private function onChange(event:TextOperationEvent){
   _text = inputTxt.text;
   
   filterData()
   
   if (text.length>=minChars) filterData();
   
   dispatchEvent(event);
  }
  
  public function filterData(){
   if (!this.focusManager || this.focusManager.getFocus()!=inputTxt) return;
   
   if (!popUp) return;
   
   collection.filterFunction = filterFunction;
   var customSort:Sort = new Sort();
   customSort.compareFunction = sortFunction
   collection.sort = customSort 
   collection.refresh()
   
   if ((text=="" || collection.length==0) && !forceOpen ){
    popUp.displayPopUp = false
   }
   else {
    popUp.displayPopUp = true
    if (requireSelection)
     list.selectedIndex = 0;
    else
     list.selectedIndex = -1;
    list.dataGroup.verticalScrollPosition = 0
    list.dataGroup.horizontalScrollPosition = 0
    list.height = Math.min(maxRows, collection.length) * 22 + 20 ;
    list.validateNow()
    popUp.width = inputTxt.width
   }
  }
  
  // default filter function
  
  public function filterFunction(item:Object):Boolean{
   var label:String = itemToLabel(item).toLowerCase();
   // prefix mode
   if (prefixOnly){
    if (label.search(text.toLowerCase()) == 0)
     return true;
    else
     return false
   }
   // infix mode
   else {
    if (label.search(text.toLowerCase()) != -1) return true;
   }
   return false;
  }
  
  public function itemToLabel(item:Object):String
  {
   if (item == null) return "";
   
   if (labelFunction)
    return labelFunction(item);
   else if (labelField && item[labelField])
    return item[labelField];
   else
    return item.toString();
  }
  
  private function returnFunction(item:Object):String{
   if (item == null) return "";
   
   if (returnField)
    return item[returnField];
   else
    return itemToLabel(item);
  }
  
  // default sorting - alphabetically ascending
  
  public var sortFunction:Function = defaultSortFunction;
   
  public function defaultSortFunction(item1:Object, item2:Object, fields:Array=null):int{
   var label1:String = itemToLabel(item1);
   var label2:String = itemToLabel(item2);
   if (label1<label2)
    return -1;
   else if (label1==label2)
    return 0;
   else
    return 1;
   
  }
  
  private function onKeyDown(event: KeyboardEvent) : void{
   
   if (popUp.displayPopUp){
    switch (event.keyCode){
     case Keyboard.UP:
     case Keyboard.DOWN:
     case Keyboard.END:
     case Keyboard.HOME:
     case Keyboard.PAGE_UP:
     case Keyboard.PAGE_DOWN:
      inputTxt.selectRange(text.length, text.length)
      list.dispatchEvent(event)
      break;
     case Keyboard.ENTER:
      acceptCompletion();
      break;
     case Keyboard.TAB:
      if (requireSelection)
       acceptCompletion();
      else
       popUp.displayPopUp = false
      break;
     case Keyboard.ESCAPE:
      popUp.displayPopUp = false
      break;
    }
   }
  }
  
  private function enter(event:FlexEvent){
   if (popUp.displayPopUp && list.selectedIndex>-1) return;
   dispatchEvent(event)
  }
  
  // this is a workaround to reset the Mouse cursor
  
  private function onMouseOut(event:MouseEvent){
   Mouse.cursor = MouseCursor.AUTO;
  }
  
  public function acceptCompletion() : void
  {
   if (list.selectedIndex >= 0 && collection.length>0)
   {
    
    _selectedIndex = list.selectedIndex
    _selectedItem = collection.getItemAt(_selectedIndex)
    
    text = returnFunction(_selectedItem)
    
    inputTxt.selectRange(inputTxt.text.length, inputTxt.text.length)
    
    var e:CustomEvent = new CustomEvent("select", _selectedItem)
    dispatchEvent(e)
    
   }
   else {
    _selectedIndex = list.selectedIndex = -1
    _selectedItem = null
   }
   
   popUp.displayPopUp = false
   
  } 
  
  public var forceOpen:Boolean = false;
  
  private function _focusInHandler(event:FocusEvent){
   if (forceOpen){
    filterData();
   }
  }
  
  private function _focusOutHandler(event:FocusEvent){
   close(event)
   
   if (collection.length==0){
    _selectedIndex = -1;
    selectedItem = null;
   }
  }
  
  private function mouseOutsideHandler(event){
   if (event is FlexMouseEvent){
    var e:FlexMouseEvent = event as FlexMouseEvent;
    if (inputTxt.hitTestPoint(e.stageX, e.stageY)) return;
   }
   
   close(event);
  }
  
  private function close(event){
   popUp.displayPopUp = false;
  }
  
  private function addClickListener(event){
   list.dataGroup.addEventListener(MouseEvent.CLICK, listItemClick)
  }
  
  private function listItemClick(event: MouseEvent) : void
  {
   acceptCompletion();
   event.stopPropagation();
  }
  
  override public function set enabled(value:Boolean) : void{
   super.enabled = value;
   if (inputTxt) inputTxt.enabled = value;
  }
  
 }
  
}

AutoCompleteSkin.mxml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<!--- AutoComplete Skin: contains a List wrapped in a PopUpAnchor and a TextInput

-->

<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
 xmlns:controls="controls.*"
    alpha.disabled=".5" xmlns:components="org.flashcommander.components.*" >

    <!-- host component -->
    <fx:Metadata>
    <![CDATA[
    /**
     * @copy spark.skins.spark.ApplicationSkin#hostComponent
     */
        [HostComponent("org.flashcommander.components.AutoComplete")]
    ]]>
    </fx:Metadata>

    <s:states>
        <s:State name="normal" />
        <s:State name="open" />
        <s:State name="disabled" />
    </s:states>
   
    <!---
        The PopUpAnchor control that opens the drop-down list.
    -->

 <s:PopUpAnchor id="popUp"  displayPopUp="false"
        top="0" bottom="0" left="0" right="0"
  popUpWidthMatchesAnchorWidth="true"
        popUpPosition="below" >
       
        <s:Group id="dropDown" minHeight="22" width="100%">
       
   <components:ListAutoComplete id="list" width="100%" minWidth="150"
           borderColor="#b4b4b4" focusAlpha="0" contentBackgroundColor="#FFFFFF" />
   
        </s:Group>
  
    </s:PopUpAnchor>
 
 <s:TextInput id="inputTxt" left="0" right="0" top="0" bottom="0"
     borderColor="#b4b4b4" focusAlpha="0" contentBackgroundColor="#FFFFFF" />


</s:Skin>

ListAutoComplete.as的代码如下:

package org.flashcommander.components
{
 import flash.events.KeyboardEvent;
 import flash.ui.Keyboard;
 
 import spark.components.List;
 
 /**
  * This list is used in AutoCompleteSkin.
  * keyDownHandler is overridden so that the list can handle keyboard events for navigation. 
  */ 
 public class ListAutoComplete extends List
 {
  
  override protected function keyDownHandler(event:KeyboardEvent):void {
   
   super.keyDownHandler(event);
   
   if (!dataProvider || !layout || event.isDefaultPrevented())
    return;
   
   adjustSelectionAndCaretUponNavigation(event);
   
  }
 }
}

CustomEvent的代码如下:

package org.flashcommander.event{

 
 import flash.events.Event;
 /**
  * <P>Custom event class.</P>
  * stores custom data in the <code>data</code> variable.
  */ 
 public class CustomEvent extends Event{
  
  public var data:Object;

  public function CustomEvent(type:String, mydata:Object, bubbles:Boolean = false, cancelable:Boolean = false){
   
   super(type, bubbles,cancelable);
   
   data = mydata;
  }

 }
}

SearchItem.mxml的代码如下

<?xml version="1.0" encoding="utf-8"?>

<!--

ADOBE SYSTEMS INCORPORATED
Copyright 2008 Adobe Systems Incorporated
All Rights Reserved.

NOTICE: Adobe permits you to use, modify, and distribute this file
in accordance with the terms of the license agreement accompanying it.

-->

<!--- The default skin class for a Spark DefaultItemRenderer class. 

@langversion 3.0
@playerversion Flash 10
@playerversion AIR 1.5
@productversion Flex 4
-->
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark"
    focusEnabled="false" mouseEnabled="false" mouseChildren="true"
    autoDrawBackground="true">
 
 <s:states>
  <s:State name="normal" />           
  <s:State name="hovered" />
  <s:State name="selected" />
  <s:State name="normalAndShowsCaret"/>
  <s:State name="hoveredAndShowsCaret"/>
  <s:State name="selectedAndShowsCaret"/>
 </s:states>
 

 <s:VGroup left="0" right="0"
     paddingLeft="2" paddingRight="2" paddingTop="2" paddingBottom="2">
  
  <s:Label text="{data.titleNoFormatting}" fontWeight="bold" fontSize="13" width="100%"  />
  
  <s:Label text="{data.url}" textDecoration="underline" color="blue" width="100%" buttonMode="true"
     click="openPage()"/>
  
 </s:VGroup>
 
 <fx:Script>
  <![CDATA[
   import flash.net.navigateToURL;
   
   function openPage(){
    navigateToURL(new URLRequest(data.url), "blank")
   }
  ]]>
 </fx:Script>
</s:ItemRenderer>

 

在主程序中引用的代码如下:

<components:AutoComplete id="geoComplete" width="100"
           forceOpen="false" prefixOnly="false" requireSelection="true"
           change="geoTextChange()" enter="this.geoComplete_selectFun.call()"
           select="this.geoComplete_selectFun.call()" />

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值