I was able to do this to add a separator component, following this ComboBox example. Here's an example with the renderer logic stripped out and the selectability logic left in:
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";
}
}
}
An alternative (still imperfect) that deals better with scrollable lists and consecutive separators:
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;
}