【发布时间】:2010-01-12 21:26:29
【问题描述】:
是否可以使 List 控件中的项目不可选?如果是这样,这将如何实现?
到目前为止,我已经尝试过一件事。我所做的是使用自定义项渲染器来检查 FlexEvent.DATA_CHANGE 事件时数据属性中的值。如果未设置该值,我尝试将项目渲染器的可选择属性设置为 false。不幸的是,这似乎不起作用。
有什么想法吗?
【问题讨论】:
标签: apache-flex actionscript-3
是否可以使 List 控件中的项目不可选?如果是这样,这将如何实现?
到目前为止,我已经尝试过一件事。我所做的是使用自定义项渲染器来检查 FlexEvent.DATA_CHANGE 事件时数据属性中的值。如果未设置该值,我尝试将项目渲染器的可选择属性设置为 false。不幸的是,这似乎不起作用。
有什么想法吗?
【问题讨论】:
标签: apache-flex actionscript-3
所以我找到了自己的解决方案。它与您的相似,并且似乎可以解决问题并涵盖所有基础,除了破解向上翻页和向下翻页键。我说 hack,因为我不确定它处理 caretIndex 的增加或减少的方式与 List 控件相同。基本上它只是手动将 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;
}
【讨论】:
我能够解决第一个/最后一个项目不可选择的问题,只需在 caretIndex++ 和 caretIndex 之前执行此 verticalScrollPosition++ 和 verticalScrollPosition-- (在上面迈克尔链接的示例中)。我不敢相信修复如此简单,但确实如此!
【讨论】:
我能够在ComboBox example 之后添加一个分隔符组件。这是一个去掉了渲染器逻辑并保留了可选择性逻辑的示例:
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";
}
}
}
一种更好地处理可滚动列表和连续分隔符的替代方案(仍然不完美):
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;
}
【讨论】:
只是想我会添加我的两种感觉。我想知道同样的事情(如何将列表设置为不可选择),我意识到 spark 组件数据组可以做到这一点。当然你需要使用 flex 4,但如果你是,并且想知道我是否可以将我的列表设置为不可选择,我建议使用数据组。
【讨论】:
我自己也在寻找解决方案,这就是我想出的解决方案。请注意,我使用的是火花列表。我希望有人觉得这很有帮助。
示例:抄袭自我的实现,我在其中构建自己的项目并使用平铺布局
<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>
【讨论】: