如何通过编程实现RecyclerView的滚动?

23

我有一个横向的recyclerView,当我第一次打开activity时,我希望让recyclerview中的所有项目滚动到底部(在这种情况下是向右),然后回到顶部(向左)。类似于动画。滚动行为应该对用户可见。

我尝试像这样做:


Animation slideRight = AnimationUtils.loadAnimation(this, R.anim.slide_right);
        Animation slideLeft = AnimationUtils.loadAnimation(this, R.anim.slide_left);
        slideRight.setDuration(1000);
        slideLeft.setDuration(1000);
        slideRight.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                recyclerView.startAnimation(slideLeft);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        recyclerView.startAnimation(slideRight);

动画向左滑动:

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false" >

    <translate
        android:duration="200"
        android:fromXDelta="-100%"
        android:fromYDelta="0%"
        android:toXDelta="0%"
        android:toYDelta="0%" />

</set>

动画向右滑动:

<translate
    android:duration="200"
    android:fromXDelta="100%"
    android:fromYDelta="0%"
    android:toXDelta="0%"
    android:toYDelta="0%" />

它可以工作,但它只是将RecyclerView作为一个整体滑动,我只想滚动(滑动)项目。我该怎么做?


速度是恒定的吗?如果是,当您有数百个项目时,它将需要很长时间,如果不是(恒定时间),则项目将在几分之一秒内显示... - pskink
我只有10个项目,这个值不会改变。 - Ege Kuzubasioglu
1
请使用 smoothScrollToPosition() - pskink
5个回答

47
你可以使用scrollToPosition()
recyclerView.post(new Runnable() {
    @Override
    public void run() {
        recyclerView.scrollToPosition(adapter.getItemCount() - 1);
        // Here adapter.getItemCount()== child count
    }
});

或者 smoothScrollToPosition()

recyclerView.post(new Runnable() {
    @Override
    public void run() {
        recyclerView.smoothScrollToPosition(adapter.getItemCount()- 1);
    }
});

要再次向上滚动,请使用索引0调用上述方法。但是首先,您需要确保RecyclerView已向后滚动到最后。
因此,在RecyclerView上放置一个ScrollListener以确保最后一个项目可见。


我认为OP想要一个展示滚动条,就像滚动到底部然后再返回来一样。 - Abbas
是的,我想是这样。谢谢你澄清。我一开始理解错了。 - ADM
@Abbas,我想表达的就是这个意思。 - Ege Kuzubasioglu
2
recyclerView.postDelayed(() -> recyclerView.smoothScrollToPosition(recyclerView.getAdapter().getItemCount() - 1), 1000);recyclerView.postDelayed(() -> recyclerView.smoothScrollToPosition(0),500); 这是一种选择,但滚动速度太快了。 - Ege Kuzubasioglu
一个布尔值可以在第一次使用时起作用。此外,在SHOWcase的情况下,必须有一个覆盖视图,以便用户在滚动列表时无法与其交互。 - ADM
显示剩余4条评论

4
请提供需要翻译的具体内容。
 int top = 0;
 recyclerView.smoothScrollToPosition(top); // for top

 int bottom = recyclerView.getAdapter().getItemCount()-1;
 recyclerView.smoothScrollToPosition(bottom);

2
如果您需要在RecyclerView中将滚动项居中显示,例如展开项目时,请使用以下方法:
在app/build.gradle中插入以下代码:
 implementation 'com.andkulikov:transitionseverywhere:1.7.4'

当在适配器的onBindViewHolder中处理点击事件时 - 插入:

AutoTransition transitionPort = new AutoTransition();
                transitionPort.setDuration(100);
                transitionPort.addListener(new Transition.TransitionListener() {
                    @Override
                    public void onTransitionStart(@NonNull Transition transition) {
                        recyclerView.setEnabled(false);
                        recyclerView.setClickable(false);
                    }

                    @Override
                    public void onTransitionEnd(@NonNull Transition transition) {
                        recyclerView.post(() -> recyclerView.smoothScrollToPosition(position));
                        recyclerView.setEnabled(true);
                        recyclerView.setClickable(true);
                    }

                    @Override
                    public void onTransitionCancel(@NonNull Transition transition) {
                        recyclerView.setEnabled(true);
                        recyclerView.setClickable(true);
                    }

                    @Override
                    public void onTransitionPause(@NonNull Transition transition) {

                    }

                    @Override
                    public void onTransitionResume(@NonNull Transition transition) {

                    }
                });
                TransitionManager.beginDelayedTransition(recyclerView, transitionPort);

1

尝试其他方法后还是不起作用吗?

这段优秀的代码对我很有用。

private void scrollToBottom(final RecyclerView recyclerView) {
    // scroll to last item to get the view of last item
    final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
    final RecyclerView.Adapter adapter = recyclerView.getAdapter();
    final int lastItemPosition = adapter.getItemCount() - 1;

    layoutManager.scrollToPositionWithOffset(lastItemPosition, 0);
    recyclerView.post(new Runnable() {
        @Override
        public void run() {
            // then scroll to specific offset
            View target = layoutManager.findViewByPosition(lastItemPosition);
            if (target != null) {
                int offset = recyclerView.getMeasuredHeight() - target.getMeasuredHeight();
                layoutManager.scrollToPositionWithOffset(lastItemPosition, offset);
            }
        }
    });
}

如果你想跳转到其他列表项而不是最后一个,可以修改行。

final int lastItemPosition = adapter.getItemCount() - 1;

源代码


0
如果有人在2023年寻找这个解决方案,这里有一种使用协程在活动中实现滚动到特定索引的方法。如果没有足够的延迟,更新列表到适配器和滚动Recycler视图的两个操作将同时进行,所以无法保证在提交列表到适配器之后才发生滚动。
 adapter.submitList(uiState.yourList) // using ListAdapter for better perfomance
 lifecycleScope.launch {
    delay(500)
    binding.rvNews.smoothScrollToPosition(INDEX_VALUE) // scrolls to the top for Index value 0
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接