2010-01-12 7 views
0

Est-il possible de rendre un élément d'un contrôle List non sélectionnable? Si oui, comment cela serait-il accompli?Est-il possible de rendre un élément d'un contrôle Liste flexible non sélectionnable?

J'ai essayé une chose jusqu'à maintenant. Ce que j'ai fait était d'utiliser un rendu d'élément personnalisé qui vérifie une valeur dans la propriété de données lors d'un événement FlexEvent.DATA_CHANGE. Si cette valeur n'est pas définie, j'ai essayé de définir la propriété selectable du rendu de l'élément sur false. Malheureusement, cela ne semble pas fonctionner.

Des idées?

Répondre

1

Alors Je suis tombé sur une solution à moi. C'est similaire au vôtre, et semble faire l'affaire et couvrir toutes les bases à part le piratage de la page et les touches de la page vers le bas. Je dis hack, parce que je ne suis pas sûr qu'il gère l'augmentation ou la diminution dans le caretIndex de la même manière que le contrôle List. Fondamentalement, il définit manuellement le caretIndex à un index avant ce que l'élément sélectionnable suivant est et modifie le code clé à un simple vers le haut ou vers le bas.

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

Ce n'est pas correct. Essayez la propriété <<< selectable >>> du contrôle LIST. –

0

J'ai été capable de faire cela pour ajouter un composant séparateur, après cela ComboBox example. Voici un exemple avec la logique de renderer dépouillé et la logique de selectability laissé dans:

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"; 
    } 

} 
} 

Une alternative (encore imparfaite) qui traite mieux avec des listes déroulantes et séparateurs consécutifs:

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

Cela fonctionne en partie. Ce qui ne semble pas prendre en compte, c'est quand une liste est défilable. Supposons par exemple que vous ayez 20 éléments dans la collection/dataProvider de votre liste, et que la liste rowCount (veiwable rows) ait la valeur 10. Ainsi, une barre de défilement est rendue.Ensuite, disons que l'index 9 (dernier élément de ligne visible lorsque la liste est vue pour la première fois) dans votre collection est un séparateur. Si vous utilisez les touches fléchées pour descendre dans la liste, le séparateur à l'index 9 est sélectionné par la liste. –

+0

Bonne capture - nous ne l'avons pas encore utilisée dans une liste déroulante. Elle ne traitait pas non plus des séparateurs consécutifs (peu susceptibles d'être utilisés par un séparateur, mais pour une utilisation raisonnable non sélectionnable). Toujours ne traite pas bien avec le premier/dernier éléments étant non sélectionnable. Il est possible qu'un bug dans ListBase - isItemSelectable() existe et soit redéfinissable, donc la navigation au clavier devrait accorder une plus grande attention à ses résultats. –

0

Je pensais juste ajouter mon double sens. Je me demandais la même chose (comment mettre une liste à ne pas sélectionner) et je me suis rendu compte que le DataGroup composant d'étincelle ferait exactement cela. bien sûr, vous devez utiliser flex 4, mais si vous êtes, et je me demande si je peux définir ma liste à ne pas sélectionner, je suggère d'utiliser le DataGroup.

1

j'ai pu résoudre le problème du premier/dernier éléments étant non sélectionnable en faisant simplement ce verticalScrollPosition ++ et verticalScrollPosition-- juste avant caretIndex ++ et caretIndex-- respectivement (dans l'exemple que Michael liée à au-dessus). Je ne pouvais pas croire que le correctif était si facile, mais c'était!

0

Je cherchais moi-même une solution et voici la solution que j'ai trouvée. Notez que j'utilise une liste d'étincelles. J'espère que quelqu'un trouve cela utile.

  1. Mettre en œuvre les deux gestionnaires d'événements pour le changement et le changement
  2. Définissez la sélection à -1 et requireSelection false de sorte que rien ne soit sélectionné
  3. Lorsque vous construisez votre dataprovider, activer/désactiver les éléments comme vous le souhaitez
  4. Fournissez une certaine logique dans le gestionnaire de changement pour appeler 'preventDefault' sur l'événement s'il n'est pas activé ou ne doit pas être sélectionné.

Exemple: cribbed de ma mise en œuvre où je construis mes propres articles et utiliser une mise en page de tuile

<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> 
Questions connexes