2010-01-12 81 views
0

是否有可能使列表控件中的項目不可選?如果是這樣,這將如何完成?是否可以使Flex List控件中的項目不可選?

到目前爲止,我已經嘗試了一件事。我所做的是使用自定義項目渲染器,在FlexEvent.DATA_CHANGE事件之後檢查data屬性中的值。如果未設置該值,則嘗試將項目渲染器的可選屬性設置爲false。不幸的是,這似乎並不奏效。

任何想法?

回答

1

所以:

package com.example.ui { 
import flash.events.MouseEvent; 
import flash.ui.Keyboard; 

import mx.controls.List; 
import mx.controls.listClasses.IListItemRenderer; 

public class MyList extends List 
{ 
    public function MyList() 
    { 
     super(); 
    } 


    /** Override mouse navigation */ 
    protected override function mouseEventToItemRenderer(event:MouseEvent):IListItemRenderer { 
     var row:IListItemRenderer = super.mouseEventToItemRenderer(event); 

     if (row != null && isSelectable(row.data)) { 
      return null; 
     } 
     return row; 
    } 

    /** Override keyboard navigation */ 
    protected override function moveSelectionVertically(code:uint, shiftKey:Boolean, ctrlKey:Boolean):void { 
     super.moveSelectionVertically(code, shiftKey, ctrlKey); 

     if (code == Keyboard.DOWN && isSeparatorData(selectedItem)) { 
      caretIndex++; 
     } 
     if (code == Keyboard.UP && isSeparatorData(selectedItem)) { 
      caretIndex--; 
     } 
     finishKeySelection();   
    } 

    /** 
    * Define this mechanism in a way that makes sense for your project. 
    */ 
    protected function isSelectable(data:Object):Boolean { 
     return data != null && data.hasOwnProperty("type") && data.type == "separator"; 
    } 

} 
} 

與滾動列表和連續分離交易更好的替代方案(尚不完善)我遇到了我自己的解決方案。它與你的類似,並且似乎能夠實現這一訣竅,並且涵蓋了除黑客和黑客之外的所有基礎。我說黑客,因爲我不確定它是否像處理List控件一樣處理caretIndex的增加或減少。基本上它只是在下一個可選項目之前手動將caretIndex設置爲索引,並將鍵碼更改爲簡單的向上或向下。

protected function disabledFilterFunction(data:Object):Boolean 
{ 
    return (data != null && data.data == null); 
} 

override protected function mouseEventToItemRenderer(event:MouseEvent):IListItemRenderer 
{ 
    var item:IListItemRenderer = super.mouseEventToItemRenderer(event); 

    if(item && item.data && disabledFilterFunction(item.data)) 
     return null; 

    return item; 
} 

override protected function moveSelectionVertically(code:uint, shiftKey:Boolean, ctrlKey:Boolean):void 
{ 
    var i:int; 
    var newIndex:int; 

    switch(code) 
    { 
     case Keyboard.UP: 
      newIndex = getPreviousUnselectableIndex(caretIndex - 1); 
      break; 

     case Keyboard.DOWN: 
      newIndex = getNextUnselectableIndex(caretIndex + 1); 
      break; 

     case Keyboard.HOME: 
      newIndex = getFirstSelectableIndex(); 
      code = Keyboard.UP; 
      break; 

     case Keyboard.END: 
      newIndex = getLastSelectableIndex(); 
      code = Keyboard.DOWN; 
      break; 

     case Keyboard.PAGE_UP: 
     { 
      newIndex = Math.max(getFirstSelectableIndex(), getPreviousUnselectableIndex(caretIndex - (rowCount - 2))); 
      code = Keyboard.UP; 
      break; 
     } 

     case Keyboard.PAGE_DOWN: 
     { 
      newIndex = Math.min(getLastSelectableIndex(), getNextUnselectableIndex(caretIndex + (rowCount - 1))); 
      code = Keyboard.DOWN; 
      break; 
     } 
    } 

    if(newIndex > -1 && newIndex < collection.length) 
    { 
     caretIndex = newIndex; 
     super.moveSelectionVertically(code, shiftKey, ctrlKey); 
    } 
} 

private function getFirstSelectableIndex():int 
{ 
    var result:int = -1; 

    for(var i:int = 0; i < collection.length; i++) 
    { 
     if(!disabledFilterFunction(collection[i])) 
     { 
      result = i + 1; 
      break; 
     } 
    } 

    return result; 
} 

private function getLastSelectableIndex():int 
{ 
    var result:int = -1; 

    for(var i:int = collection.length - 1; i > -1; i--) 
    { 
     if(!disabledFilterFunction(collection[i])) 
     { 
      result = i - 1; 
      break; 
     } 
    } 

    return result; 
} 

private function getPreviousUnselectableIndex(startIndex:int):int 
{ 
    var result:int = -1; 

    for(var i:int = startIndex; i > -1; i--) 
    { 
     if(!disabledFilterFunction(collection[i])) 
     { 
      result = i + 1; 
      break; 
     } 
    } 

    return result; 
} 

private function getNextUnselectableIndex(startIndex:int):int 
{ 
    var result:int = collection.length; 

    for(var i:int = startIndex; i < collection.length; i++) 
    { 
     if(!disabledFilterFunction(collection[i])) 
     { 
      result = i - 1; 
      break; 
     } 
    } 

    return result; 
} 
+0

這不好。嘗試LIST控件的屬性<<< selectable >>>。 – 2010-12-29 09:53:34

0

我能夠做到這一點,添加一個分隔符組件,繼此ComboBox example。下面是一個例子與渲染邏輯剝離出來,並在離開可選擇性邏輯:

protected override function moveSelectionVertically(code:uint, shiftKey:Boolean, ctrlKey:Boolean):void { 
     super.moveSelectionVertically(code, shiftKey, ctrlKey); 

     var newCode:uint = singleLineCode(code); 
     var item:Object = selectedItem; 
     var itemChanged:Boolean = true; 

     while (!isNaN(newCode) && itemChanged && isSeparatorData(item)) { 
      super.moveSelectionVertically(newCode, shiftKey, ctrlKey); 
      itemChanged = (item === selectedItem); 
      item = selectedItem; 
     } 
    } 

    private function singleLineCode(code:uint):uint { 
     switch (code) { 
     case Keyboard.UP: 
     case Keyboard.PAGE_UP: 
      return Keyboard.UP; 
      break; 
     case Keyboard.DOWN: 
     case Keyboard.PAGE_DOWN: 
      return Keyboard.DOWN; 
      break; 
     default: 
      return NaN; 
      break;        
     } 
     return code; 
    } 
+0

這部分工作。它似乎沒有考慮到的是列表是可滾動的。假設你的列表的collection/dataProvider中有20個項目,並且列表rowCount(veiwable rows)是10.因此,一個滾動條被渲染。然後讓我們說你的集合中的索引9(當列表第一次查看時最後一個可見的行項目)是分隔符。如果您使用箭頭鍵在列表中向下移動,則列表中將選擇索引9處的分隔符。 – 2010-01-13 19:26:57

+0

好的結果 - 迄今爲止我們還沒有在一個可滾動列表中使用它。 它也沒有處理連續的分隔符(不太可能用於分隔符的使用,但是用於合理的非可選用法)。仍不能很好地處理不可選擇的第一個/最後一個項目。 可以說ListBase中的一個錯誤isItemSelectable()存在並且可以覆蓋,所以鍵盤導航應該更加註意其結果。 – 2010-01-13 23:35:26

0

只是想我會加上我的兩個意義。我想知道同樣的事情(如何設置一個列表不可選),我意識到spark組件數據組完全可以做到這一點。當然你需要使用flex 4,但如果你是,並想知道我可以設置我的列表不可選,我建議使用數據組。

1

我能夠通過簡單地在caretIndex ++和caretIndex--之前(在Michael鏈接上面的示例中)簡單地執行verticalScrollPosition ++和verticalScrollPosition來修復第一個/最後一個項不可選擇的問題。我無法相信修復是如此簡單,但它是!

0

我一直在尋找解決方案,這裏是我想出的解決方案。請注意,我正在使用一個火花列表。我希望有人認爲這有幫助。

  1. 實現這兩個事件處理程序的變化和改變
  2. 所以,沒有什麼選擇
  3. 當你建立你的數據提供程序,根據需要啓用/禁用項目設置選擇爲-1和requireSelection假
  4. 在更改處理程序中提供一些邏輯,以在事件未啓用時調用「preventDefault」,或者不應該選擇此選項。

示例:從我的實現其中那兒剽竊我建立我自己的項目和使用tile佈局

<s:List id="myListView" 
    itemRenderer="spark.skins.spark.DefaultComplexItemRenderer" 
    horizontalCenter="0" 
    verticalCenter="0" 
    borderVisible="false" 
    dataProvider="{myItems}" 
    change="changeHandler(event)" changing="changingHandler(event)" 
    requireSelection="false" 
    selectedIndex="-1" > 
    <s:layout> 
     <s:TileLayout verticalGap="0" /> 
    </s:layout> 
</s:List> 
<fx:script> 
    <![CDATA[ 
     import mx.collections.ArrayCollection;    
     import spark.events.IndexChangeEvent; 

     [Bindable] 
     public var myItems = new ArrayCollection; 


     protected function startup():void { 
      // Here's where you'd build up your items if they 
      // need to be built dynamically. 
     } 

     protected function changeHandler(event:IndexChangeEvent):void 
     { 
      var currentIndx:int = event.currentTarget.selectedIndex; 
      var selectedItem:UIComponent = event.currentTarget.selectedItem as UIComponent; 

      // Do whatever you need to do on selection here 
     } 

     protected function canMicrophoneChange(event:IndexChangeEvent):void 
     { 
      var currentIndx:int = event.currentTarget.selectedIndex; 
      var selectedItem:UIComponent = event.currentTarget.selectedItem as UIComponent; 

      // This will cancel the select if the item was not enabled. 
      if (selectedItem.enabled == false) event.preventDefault(); 
     } 
    ]]> 
</fx:script> 
相關問題