smoothScrollToPosition() only scrolls partway in Android ICS?
Asked Answered
A

5

6

In Gingerbread, I had no issues with using smoothScrollToPosition() to scroll across dozens of items at a time. After my Nexus S was upgraded to Ice Cream Sandwich, I noticed that no matter what I put in smoothScrollToPosition(), it will only scroll about a couple of hundred pixels in either direction, and then stop.

Is this a known issue with ICS? I've noticed this with the Galaxy Nexus as well. I've looked at a few other questions and tried a few different tricks, such as turning off calls to notifyDataSetChanged(), and posting the smoothScrollToPosition() as a delayed runnable, but unfortunately, it doesn't want to scroll more than a hundred pixels or so before stopping. :(

Adur answered 4/7, 2012 at 18:56 Comment(2)
I'm having the same issue. code.google.com/p/android/issues/detail?id=37278Rolandrolanda
It seems to be fixed in Jellybean.Adur
A
12

Appears to be an issue with the duration required to finish the animation, the same issue is present with smoothScrollBy(int distance, int duration), at cursory glance, smoothScrollToPosition() is a friendly wrapper around smoothScrollBy() that does a lot of the legwork. smoothScrollBy() in turn is faking a "fling gesture", as if a user had made the motion.

smoothScrollBy really just posts the fling runnable that continues to repost itself till the duration runs out. Meaning that it simply computes the scroll offset required based on the offset it previously decided to move to, hence if duration runs out before it gets to the target offset, it stops at the last offset calculated. (Rather than all of sudden jumping to the target offset, which is perhaps more jarring as it would not be animated).

The difficulty for the Android guys is determining how much to move by each run() call to reach the required offset because ListView cells (children) are entirely dynamic in height, so they can't just do a simple distance calculation as the non-visible children's height are unknown to them. It is the same reason the Android scrollbar can fluctuate in size as you scroll, it has to take a best guess at how big it should be based on what it is currently seeing.

Anyway that doesn't help you solve it but some one might find it interesting :)

If you know you have static cell heights however, you can write your own method to calculate the distance and duration to pass to smoothScrollBy() yourself and have a static amount of time to move X distance. If you don't, it will have to suffice to use the solution bigstones posted, which really is working because of the high SCROLL_DURATION of 1000ms. You can take the ICS version and change this attribute as well, rather than using the 2.2 version, which is not the root cause.

You can also adapt those runnables with your own custom algorithm, it shouldn't be too difficult to tweak things.

Andean answered 14/9, 2012 at 5:24 Comment(0)
L
2

This is what I did to resolve the issue. Essentially, we want to keep calling smoothscrolling until you reach the desired element (in this case, I simply want to scroll to the top, which is element 0).

//There is a known bug where smoothScrollToPosition(..) may not reach the top, 
            //if the list is very large, keep scrolling until you reach the top element
            newsFeed.setOnScrollListener(new OnScrollListener() {
                @Override
                public void onScrollStateChanged(AbsListView view, int scrollState) {

                }

                @Override
                public void onScroll(AbsListView view, int firstVisibleItem,
                        int visibleItemCount, int totalItemCount) {
                    if(firstVisibleItem != 0) {
                        newsFeed.smoothScrollToPosition(0);
                    } 
                    else {
                        //We are done
                        newsFeed.setOnScrollListener(null);
                    }
                }
            });
            newsFeed.smoothScrollToPosition(0);
Legionary answered 4/7, 2013 at 14:53 Comment(0)
U
2

If your goal is to scroll to the top, consider using smoothScrollToPositionFromTop(0,0). instead.

Unwind answered 10/1, 2014 at 20:36 Comment(0)
S
0

Because the ListView uses the getChildCount() method to get the position count in AbsListView.java source code. but in ListView the getChildCount() method can't get the correctly count. Maybe you should use setSelection() method.

Substratosphere answered 27/9, 2012 at 7:36 Comment(0)
G
0

I have an issue on ICS too.

I have a chat message list activity, everytime after i send the message, i need to scroll the listview to bottom smoothly. So after i called notifyDataSetChanged(), i called method smoothScrollToPosition(). On other android build versions, it works well. But on ICS, it is very strange. If my listview is at bottom, i tested 3 cases. if I append one new item to the listview, it won't scroll. If i append two new items to the list view --> it will scroll well. And If i scroll the listview up a few pixes, after i append one new item, it will scroll well. After a lot of google search and test, i feel helplessness about this. At last, every time i setdata to listview, i append an empty view(1px) at the last position, though this is not a good method, but it works for me.

Gap answered 24/9, 2013 at 11:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.