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();
}