我是 Flex/ActionScript 的新手(到目前为止,.NET/Java 一直是我的主要游乐场)。我正在尝试构建一个具有列表的 Flex 应用程序,该列表的外观和行为就像一个无限列表(项目 - 可以是任何对象)。这个想法是用户应该能够向上或向下滚动并且永远不会在任一方向上到达列表的末尾。
一个例子是数字列表。向上滚动将显示负数;向下滚动将显示积极的。现在,我的列表是一个简单的 Flex Spark 列表(使用 Flex Hero)。它绑定到一个 ArrayList 的数据提供者。
我最初的想法是监听滚动事件并根据需要添加/删除项目。但是,在 Flex Hero 的当前版本中,有一个错误有时不会引发垂直滚动条的滚动事件 ( http://bugs.adobe.com/jira/browse/SDK-26533 )。
所以,我正在使用上面链接中建议的解决方法(即监听列表滚动器视口的 propertyChanged 事件。该事件虽然只给了我当前的verticalScrollPosition。
而且看起来默认的火花列表支持平滑滚动并在列表滚动停止之前多次引发事件(这是一个很好的视觉效果)。
现在,我需要:
- 弄清楚它是向上滚动还是向下滚动(我该怎么做?)
找出哪些项目是可见的。我可以从:
list.dataGroup.getItemIndicesInView()
根据需要添加/删除项目,以便用户可以永远上下滚动,永远不会到达列表的末尾。
我已经尝试了以下代码,但它不起作用。(代码中的注释)。
那里有任何 Flex 专家吗?请帮忙。
import mx.collections.ArrayList;
import mx.core.INavigatorContent;
import mx.events.FlexEvent;
import mx.events.PropertyChangeEvent;
var listData:ArrayList;
var firstItemInView:int = 0;
var lastItemInView:int = 0;
var count = 0;
//gets the currently visible item indices (first and last)
private function getVisibleIndices():Vector.<int> {
var ind:Vector.<int> = new Vector.<int>(2, true);
ind[0] = firstItemInView;
ind[1] = lastItemInView;
return ind;
}
protected function view_creationCompleteHandler(event:FlexEvent):void {
//create an initialise list data
listData = new ArrayList();
for(var i:int = 0; i < 6; i++){
listData.addItemAt(i, i);
}
infiniteList.dataProvider = listData;
updateIndices();
infiniteList.scroller.viewport.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, infiniteList_VerticalScroll_PropertyChanged);
}
//get the indices visible from the list's data group
private function getNewIndices():Vector.<int> {
var indices:Vector.<int> = new Vector.<int>(2, true);
var indicesInView:Vector.<int> = infiniteList.dataGroup.getItemIndicesInView();
if (indicesInView.length > 0){
indices[0] = indicesInView[0];
}
if (indicesInView.length > 1){
indices[1] = indicesInView[indicesInView.length - 1];
}
return indices;
}
private function updateIndices():void {
var indices:Vector.<int> = getNewIndices();
if (indices.length > 0){
firstItemInView = indices[0];
if (indices.length > 1){
lastItemInView = indices[1];
}
}
}
protected function leftCalendar_VerticalScroll_PropertyChanged(event:PropertyChangeEvent):void {
switch (event.property){
case "verticalScrollPosition":
var indices:Vector.<int> = getNewIndices();
var oldIndices:Vector.<int> = getVisibleIndices();
var newNum:Number;
if (indices[1] - indices[0] == 2 && (oldIndices[0] != indices[0] && oldIndices[1] != indices[1])){
//a new item is in view. did we scroll up or down?
if (oldIndices[0] < indices[0]){
count++;
trace(count + " up : old[" + oldIndices[0] + "," + oldIndices[1] + "], new[" + indices[0] + "," + indices[1] + "]");
//newNum = Number(listData.getItemAt(listData.length - 1)) + 1;
//trace("new number to add: " + newNum);
//trace("todo remove: " + listData.getItemAt(0));
fixItems({ addAt : "top", removeAt : "bottom", newValue : newNum});
} else {
trace("down : old[" + oldIndices[0] + "," + oldIndices[1] + "], new[" + indices[0] + "," + indices[1] + "]");
fixItems({ addAt : "bottom", removeAt : "top", newValue : newNum});
}
//update indices:
updateIndices();
var newOnes = getVisibleIndices(); //seems to be getting the new ones, but the next occurance of this event handler doesn't pick up the new values! why?
trace(count + " current[" + newOnes[0] + ", " + newOnes[1] + "]");
}
break;
}
}
protected function fixItems(data:Object):void {
var item:Object;
//add a new item
if (data.addAt == "top"){
listData.addItemAt(data.newValue, 0);
} else {
listData.addItem(data.newValue);
}
//remove one of the existing ones
if (data.removeAt == "top"){
item = listData.getItemAt(0);
trace("removing " + item);
listData.removeItemAt(0);
} else {
item = listData.getItemAt(listData.length - 1);
trace("removing " + item);
listData.removeItemAt(listData.length - 1);
}
updateIndices();
}