smoothScrollToPosition()仅在Android ICS中滚动?

时间:2012-07-04 18:56:06

标签: android android-4.0-ice-cream-sandwich

在Gingerbread中,我使用smoothScrollToPosition()一次滚动数十个项目没有任何问题。在我的Nexus S升级为冰淇淋三明治之后,我注意到无论我放在smoothScrollToPosition()中,它都只会在任一方向上滚动大约几百个像素,然后停止。

这是ICS的已知问题吗?我也注意到Galaxy Nexus。我已经看了几个其他的问题并尝试了一些不同的技巧,比如关闭对notifyDataSetChanged()的调用,并将smoothScrollToPosition()作为延迟的runnable发布,但不幸的是,它不想滚动超过一个停止前一百个像素左右。 :(

5 个答案:

答案 0 :(得分:12)

似乎是完成动画所需的持续时间的问题,smoothScrollBy(int distance,int duration)存在同样的问题,粗略地看一眼,smoothScrollToPosition()是一个友好的smoothScrollBy()包装器很多腿部。 smoothScrollBy()反过来假装“fling手势”,好像用户做了动作一样。

smoothScrollBy实际上只是发布了持续重新发布的fling runnable,直到持续时间用完为止。这意味着它只是根据之前决定移动到的偏移量来计算所需的滚动偏移量,因此如果持续时间在达到目标偏移量之前耗尽,则会在计算的最后一个偏移量处停止。 (而不是突然跳到目标偏移,这可能会更加刺耳,因为它不会被动画化。)

Android人员的困难在于确定每次run()调用移动多少以达到所需的偏移量,因为ListView单元格(子级)的高度完全是动态的,所以他们不能只做一个简单的距离计算他们不知道不可见的孩子的身高。这与滚动时Android滚动条的大小波动的原因相同,它必须根据当前看到的内容对其大小进行最佳猜测。

无论如何,这并没有帮助你解决它,但有些人可能会觉得有趣:)

如果你知道你有静态单元格高度,你可以编写自己的方法来计算自己传递给smoothScrollBy()的距离和持续时间,并有一个静态的时间来移动X距离。如果你不这样做,那么就必须使用已发布的解决方案bigstones,因为170ms的SCROLL_DURATION很高,所以它确实有效。您也可以使用ICS版本并更改此属性,而不是使用2.2版本,这不是根本原因。

您还可以使用自己的自定义算法调整这些runnables,调整内容应该不会太难。

答案 1 :(得分:2)

这就是我解决这个问题的方法。基本上,我们希望继续调用smoothscrolling直到你到达所需的元素(在这种情况下,我只想滚动到顶部,即元素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);

答案 2 :(得分:2)

如果您的目标是滚动到顶部,请考虑使用smoothScrollToPositionFromTop(0,0)。代替。

答案 3 :(得分:0)

因为ListView使用getChildCount()方法来获取AbsListView.java源代码中的位置计数。但是在ListView中,getChildCount()方法无法正确计数。也许你应该使用setSelection()方法。

答案 4 :(得分:0)

我在ICS上也遇到了问题。

我有一个聊天消息列表活动,每次发送消息后,我都需要将listview顺利滚动到底部。所以在我调用notifyDataSetChanged()之后,我调用了方法smoothScrollToPosition()。在其他Android构建版本上,它运行良好。但在ICS上,这很奇怪。如果我的列表视图位于底部,我测试了3个案例。如果我将一个新项目附加到列表视图,它将不会滚动。如果我将两个新项目附加到列表视图 - >它会很好地滚动。如果我将listview滚动几个像素,在我添加一个新项目之后,它将滚动得很好。经过大量的谷歌搜索和测试,我对此感到无助。最后,每当我将数据设置为listview时,我会在最后一个位置添加一个空视图(1px),虽然这不是一个好方法,但它对我有用。