开发者

Flex Spark List scroll to bottom when new data is added

开发者 https://www.devze.com 2023-01-18 20:13 出处:网络
I have a Spark List (spark.components.List) backed by an ArrayCollection for its dataProvider. The List has a vertical scrollbar when there\'s too many rows to display. What I want is when a new row i

I have a Spark List (spark.components.List) backed by an ArrayCollection for its dataProvider. The List has a vertical scrollbar when there's too many rows to display. What I want is when a new row is added to the List for it to scroll to the bottom to show that new row.

I've tried calling List's ensureIndexIsVisible from a listener on the ArrayCollection. This doesn't work because the List hasn't yet fully rendered the new row. It will either scroll to the second from the last row, or throw the exception:

Error: invalidIndex
 at spark.layouts.supportClasses::LinearLayoutVector/start()[E:\dev\4.0.0\frameworks\projects\spark\src\spark\layouts\supportClasses\LinearLayoutVector.as:893]
 at spark.layouts.supportClasses::LinearLayoutVector/getBounds()[E:\dev\4.0.0\frameworks\projects\spark\src\spark\layouts\supportClasses\LinearLayoutVector.as:1117]
 at spark.layouts::VerticalLayout/getElementBounds()[E:\dev\4.0.0\frameworks\projects\spark\src\spark\layouts\VerticalLayout.as:852]
 at spark.layouts.supportClasses::LayoutBase/http://www.adobe.com/2006/flex/mx/internal::getScrollPositionDeltaToElementHelper()[E:\dev\4.0.0\frameworks\projects\spark\src\spark\layouts\supportClasses\LayoutBase.as:1367]
 at spark.layouts.supportClasses::LayoutBase/getScrollPositionDeltaToElement()[E:\dev\4.0.0\frameworks\projects\spark\src\spark\layouts\supportClasses\LayoutBase.as:1348]
 at spark.components::List/ensureIndexIsVisible()[E:\dev\4.0.0\framewor开发者_JS百科ks\projects\spark\src\spark\components\List.as:2105]

I've made sure that my listener is added to the ArrayCollection after setting List's dataProvider. The hope is that I'd be calling ensureIndexIsVisible after the List got a chance to process the new row. My guess is that the List doesn't render the row until some redraw event that occurs later (after I've called ensureIndexIsVisible).

I've also tried specifying a VerticalLayout and setting its verticalScrollPosition to an overly large number (like 99999). This has the same problem - it scrolls to the second from the last row.

So, is there a way to scroll to a newly added row in a Spark List? The only I could find on the Internet is this poorly formatted flexcoders thread.


Instead of extending List in order to override updateDisplayList, I added a listener to the FlexEvent.UPDATE_COMPLETE on my List component and it works just fine for me.


My solution was to extend List and override updateDisplayList, which works:

protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
    super.updateDisplayList(unscaledWidth, unscaledHeight);
    // call ensureIndexIsVisible here
}

See discussion on Adobe's forums.


I found that when ensureIndexIsVisible is run directly after an insert to a list dataProvider it does not accurately pull the position of the last item in the list. This looks to be because the binding has not had a chance to update the list. The fastest solution for me was to run a callLater on ensureIndexIsVisible.

_acGuestBookMessages.addItemAt(obj, _acGuestBookMessages.length);
var arr:Array = [_acGuestBookMessages.length-1];
callLater(lstGuestBookMessages.ensureIndexIsVisible, arr);


Want to scroll to bottom of an updating spark list and ensureIndexIsVisible is too much undocumented trouble? I got this to work by dealing with the physical height of dataGroup property on List...

function newMessage(...)
{
    messages.addItemAt(msg, messages.length);               
    messages.refresh();
    scrollToBottom();
}

function scrollToBottom():void
{
    messagesList.addEventListener("updateComplete", scrollUpdate);
}

private function scrollUpdate(e:Event):void
{
    messagesList.removeEventListener("updateComplete", scrollUpdate);
    messagesList.dataGroup.verticalScrollPosition = messagesList.dataGroup.contentHeight - messagesList.dataGroup.height;
}


if(itemsList && itemsList.scroller && 
   itemsList.scroller.verticalScrollBar && 
   itemsList.scroller.verticalScrollBar.visible){

       itemsList.scroller.verticalScrollBar.value = 
          itemsList.scroller.verticalScrollBar.maximum;

}


Was having the same problem, this works for me -

if(chatCollection.length > 0)
{
    chatList.validateNow();
    chatList.ensureIndexIsVisible(chatCollection.length - 1);
}
0

精彩评论

暂无评论...
验证码 换一张
取 消