smoothScrollToPosition() only scrolls partway in Android ICS?

前端 未结 5 1841
闹比i
闹比i 2021-02-04 18:05

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 th

相关标签:
5条回答
  • 2021-02-04 18:42

    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.

    0 讨论(0)
  • 2021-02-04 18:43

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

    0 讨论(0)
  • 2021-02-04 18:50

    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.

    0 讨论(0)
  • 2021-02-04 19:06

    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.

    0 讨论(0)
  • 2021-02-04 19:07

    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);
    
    0 讨论(0)
提交回复
热议问题