等待 ListView 的 smoothScrollToPosition() 完成

发布于 2024-12-12 13:40:57 字数 1138 浏览 1 评论 0原文

范围

我需要平滑滚动到某个位置,然后使用 setSelection(anotherPosition)“跳转”到另一个位置。这样做是为了在 ListView 中创建(例如)100 个项目平滑滚动的错觉。 smoothScrollToPosition(100) 持续时间太长了,你知道。

问题

setSelection() 不会等到 smoothScrollToPosition 完成其工作,因此 setSelection() 立即被调用,用户只能看到快速跳转;

代码

private final int scrollableItems = 20;

int firstVisiblePosition = mListView.getFirstVisiblePosition();
if (firstVisiblePosition < scrollableItems) {
    mListView.smoothScrollToPosition(0);
} else {
    mListView.smoothScrollToPosition(firstVisiblePosition - scrollableItems);
    mListView.setSelection(0);
}
mListView.clearFocus();

想法

好的,我们可以改变平滑幻觉的逻辑:首先 setSelection(),然后平滑滚动(我们滚动到列表顶部的第一项):

    int firstVisiblePosition = mListView.getFirstVisiblePosition();

    if (firstVisiblePosition < scrollableItems) {
        mListView.smoothScrollToPosition(0);
    } else {
        mListView.setSelection(scrollableItems);
        mListView.smoothScrollToPosition(0);
    }
    mListView.clearFocus();

Scope

I need to scroll to certain position smoothly and then "jump" to another position with setSelection(anotherPosition). This is done to create an illusion of smooth scrolling of (e.g.) 100 items in ListView. smoothScrollToPosition(100) lasts too much, you know.

Problem

setSelection() doesn't wait till smoothScrollToPosition finishes its work, so setSelection() is being called immediately and user sees quick jumping only;

Code

private final int scrollableItems = 20;

int firstVisiblePosition = mListView.getFirstVisiblePosition();
if (firstVisiblePosition < scrollableItems) {
    mListView.smoothScrollToPosition(0);
} else {
    mListView.smoothScrollToPosition(firstVisiblePosition - scrollableItems);
    mListView.setSelection(0);
}
mListView.clearFocus();

Idea

OK, we could change logic of smoothness illusion: first setSelection(), then scroll smoothly (we're scrolling to the very first item on top of the list):

    int firstVisiblePosition = mListView.getFirstVisiblePosition();

    if (firstVisiblePosition < scrollableItems) {
        mListView.smoothScrollToPosition(0);
    } else {
        mListView.setSelection(scrollableItems);
        mListView.smoothScrollToPosition(0);
    }
    mListView.clearFocus();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苦笑流年记忆 2024-12-19 13:40:57
final ListView listView = ...;
View listItemView = ...;
listView.smoothScrollBy(listItemView.getHeight() * NUMBER_OF_VIEWS, 
    DURATION * 2);
listView.postDelayed(new Runnable() {
    public void run() {
        listView.smoothScrollBy(0, 0); // Stops the listview from overshooting.
        listView.setSelection(0);
    }
}, DURATION);

当然,需要根据您的用例调整滚动方向等(转到列表顶部)

编辑:如果滚动速度太高,旧解决方案可能会过度调整, smoothScrollBy(0,0) 将在立即正确设置选择之前停止平滑滚动。

final ListView listView = ...;
View listItemView = ...;
listView.smoothScrollBy(listItemView.getHeight() * NUMBER_OF_VIEWS, 
    DURATION * 2);
listView.postDelayed(new Runnable() {
    public void run() {
        listView.smoothScrollBy(0, 0); // Stops the listview from overshooting.
        listView.setSelection(0);
    }
}, DURATION);

Of course, direction of the scroll etc. would need to be adjusted for your use case (go to the top of the list)

EDIT: Old solution could overshoot if the velocity of the scroll was too high, smoothScrollBy(0,0) will stop the smooth scrolling before setting the selection properly and immediately.

迷雾森÷林ヴ 2024-12-19 13:40:57

另一种方法是添加 OnScrollListener。

private final int scrollableItems = 20;

int firstVisiblePosition = mListView.getFirstVisiblePosition();
if (firstVisiblePosition < scrollableItems) {
    mListView.smoothScrollToPosition(0);
} else {

    mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
      @Override
      public void onScrollStateChanged(AbsListView absListView, int i) {
        if (i == SCROLL_STATE_IDLE) {
          mListView.setSelection(0);
           }
      }
   })

   mListView.smoothScrollToPosition(firstVisiblePosition - scrollableItems);
}
mListView.clearFocus();

Another way is to add an OnScrollListener.

private final int scrollableItems = 20;

int firstVisiblePosition = mListView.getFirstVisiblePosition();
if (firstVisiblePosition < scrollableItems) {
    mListView.smoothScrollToPosition(0);
} else {

    mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
      @Override
      public void onScrollStateChanged(AbsListView absListView, int i) {
        if (i == SCROLL_STATE_IDLE) {
          mListView.setSelection(0);
           }
      }
   })

   mListView.smoothScrollToPosition(firstVisiblePosition - scrollableItems);
}
mListView.clearFocus();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文