如何在 Flex 中实现无限列表(英雄)
我是 Flex/ActionScript 的新手(到目前为止,.NET/Java 一直是我的主要游乐场)。 我正在尝试构建一个 Flex 应用程序,它有一个列表,该列表的外观和行为就像一个无限列表(项目 - 可以是任何对象)。这个想法是,用户应该能够向上或向下滚动,并且永远不会在任一方向到达列表的末尾。
一个例子是数字列表。向上滚动会显示负数;向下滚动将显示积极的内容。现在,我的列表是一个简单的 Flex Spark 列表(使用 Flex Hero)。 它绑定到一个 ArrayList 数据提供者。
我最初的想法是监听滚动事件并根据需要添加/删除项目。但是,在 Flex Hero 的当前版本中,存在一个错误,有时不会引发垂直滚动条的滚动事件(http://bugs.adobe.com/jira/browse/SDK-26533)。
因此,我正在使用上面链接中建议的解决方法(即侦听列表滚动器视口的 propertyChanged 事件。该事件虽然只提供当前的 VerticalScrollPosition。
而且看起来默认的 Spark 列表支持平滑滚动并引发在列表滚动停止之前多次发生事件(这是一个很好的视觉效果)。
现在,我需要:
- 弄清楚它是向上还是向下滚动(我该怎么做?)
找出哪些项目。我可以从以下位置获取:
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();
}
I'm new to Flex/ActionScript (.NET/Java has been my main playground so far).
I'm trying to build a Flex app that has a list that is meant to look and behave like an infinite list (of items - which can be any object). The idea is that the user should be able to scroll up or down and never reach the end of the list in either direction.
An example would be a list of numbers. Scrolling up will show negative numbers; scrolling down will show positive ones. Now, my list is a simple Flex Spark list (using Flex Hero).
It is bound to a data provider that is an ArrayList.
My initial idea was to listen to the scroll event and add/remove items as needed. However, in the current build of Flex Hero, there is a bug that doesn't raise scroll events for vertical scrollbars sometimes (http://bugs.adobe.com/jira/browse/SDK-26533).
So, I'm using the workaround suggested in the link above (i.e listening to the propertyChanged event of the list's scroller's viewport. The event though only gives me the current verticalScrollPosition.
And it looks like the default spark list supports smooth scrolling and raises the event many times before the list scrolling comes to a standstill (it is a nice visual effect).
Now, I need to :
- Figure out whether it is scrolling up or down (how do I do that?)
Figure out which items are visible. I can get this from:
list.dataGroup.getItemIndicesInView()
Add/remove items as needed, so that the user can scroll up and down forever, never reaching the end of the list in either direction.
I've tried the following code but it doesn't work. (comments in code).
Any Flex experts out there? Please help.
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();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您不能使用列表。您必须从头开始为此创建自己的自定义组件。据我所知,Flex 中的所有组件都使用有限的 dataProvider 来显示信息。如果您想要无限,您需要创建自己的组件来处理一个范围(或任何范围)并适当地显示它并滚动它。请务必清除不再显示的任何项目(或重复使用它们),因为这将导致严重的内存泄漏。
You can't use a List. You'll have to create your own custom component for this from scratch. All components that I know of in Flex uses a finite dataProvider to display information. If you want infinite, you'll need to create your own component that can handle a range (or none whatsoever) and display it appropriately and scroll it. Be sure to clean any items that are not displayed anymore (or reuse them) because that would be a severe memory leak.
我认为您需要创建自定义列表控件,该控件为 UI 循环 arraycollection/arraylist 项目,
ArrayCollection/Array/ArrayList 应该仅用于保存诸如项目的线性列表之类的数据,并且列表控件应该以循环方式显示项目
编辑
我正在尝试回答您修改列表中的数据和滚动方向的问题
希望这会有所帮助
注意
函数 ltClicked 和 rtClicked 正在修改列表数据
滚动用于获取方向
我认为更好的方法是扩展列表控件以获取方向和滚动位置
并操作数组来添加或删除列表中的项目
I think you need to create your custom List control, which circulate arraycollection/arraylist item for UI,
ArrayCollection/Array/ArrayList should only be use to hold data like liner list of items, and list Control should display items in circular fashion
EDITED
I am trying to ans your question modifying data in list and direction of scroll
hopefully this will help
NOTE
Function ltClicked and rtClicked are modifying List data
and scrolled is used get to direction
I think better way of doing this is extend List control to get direction and scroll position
and manipulate Array to add or remove items in list
可以尝试 InfiniteScrollList 类::
InfiniteListModel 类:
详细请参考以下内容:
http://www.tricedesigns.com/ 2011/10/26/infinitely-scrolling-lists-in-flex-applications/
May try InfiniteScrollList class::
InfiniteListModel class:
For details, please refer to the following:
http://www.tricedesigns.com/2011/10/26/infinitely-scrolling-lists-in-flex-applications/