6

在 Gingerbread 中,我对使用 smoothScrollToPosition() 一次滚动几十个项目没有任何问题。在我的 Nexus S 升级到 Ice Cream Sandwich 之后,我注意到无论我在 smoothScrollToPosition() 中放入什么,它都只会在任一方向滚动大约几百像素,然后停止。

这是 ICS 的已知问题吗?我在 Galaxy Nexus 上也注意到了这一点。我查看了其他一些问题并尝试了一些不同的技巧,例如关闭对 notifyDataSetChanged() 的调用,并将 smoothScrollToPosition() 发布为延迟可运行,但不幸的是,它不想滚动超过一百像素左右才停下来。:(

4

5 回答 5

12

似乎是完成动画所需的持续时间的问题,smoothScrollBy(int distance, int duration) 也存在同样的问题,粗略一瞥,smoothScrollToPosition() 是围绕 smoothScrollBy() 的友好包装,它做了很多跑腿。反过来,smoothScrollBy() 正在假装“挥动手势”,就好像用户做出了动作一样。

smoothScrollBy 实际上只是发布了可继续重新发布的可运行文件,直到持续时间用完为止。这意味着它只是根据之前决定移动到的偏移量计算所需的滚动偏移量,因此如果持续时间在它到达目标偏移量之前用完,它会在最后计算的偏移量处停止。(而不是突然跳到目标偏移,这可能更不和谐,因为它不会被动画化)。

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

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

但是,如果您知道自己有静态单元格高度,则可以编写自己的方法来计算传递给 smoothScrollBy() 的距离和持续时间,并有固定的时间来移动 X 距离。如果您不这样做,则必须使用发布的解决方案 bigstones 就足够了,由于 1000 毫秒的高 SCROLL_DURATION,这确实有效。您也可以使用 ICS 版本并更改此属性,而不是使用 2.2 版本,这不是根本原因。

您还可以使用自己的自定义算法调整这些可运行文件,调整这些东西应该不会太难。

于 2012-09-14T05:24:43.873 回答
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);
于 2013-07-04T14:53:25.273 回答
2

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

于 2014-01-10T20:36:58.350 回答
0

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

于 2012-09-27T07:36:19.327 回答
0

我也有关于 ICS 的问题。

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

于 2013-09-24T11:24:47.910 回答