(平滑)ScrollToPosition无法与RecyclerView一起正常工作

时间:2015-06-15 12:55:43

标签: android scroll android-recyclerview smooth-scrolling gridlayoutmanager

我使用基本的RecyclerView和GridLayoutManager。我观察到,smoothScrollToPosition和scrollToPosition也没有正常工作。

a)使用smoothScrollToPosition时,我经常收到来自RecyclerView

的错误
  

" RecyclerView:平滑滚动时传递到目标位置。"

并且RecyclerView未正确滚动(通常会错过目标行)。这主要是在我尝试滚动到某行的第一项时

b)使用scrollToPosition时似乎工作得很好,但大部分时间我只能看到该行的第一项而其余部分都没有显示。

你能给我一些提示,告诉我如何正确地使用其中一种方法吗?

非常感谢!

17 个答案:

答案 0 :(得分:55)

Finally I was able to make it work! LinearLayoutManager.scrollToPositionWithOffset(int, int) did the trick.

答案 1 :(得分:14)

我也有同样的问题,但通过自定义SmoothScroller

设法解决了这个问题

让Custom LayoutManager如下所示

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var player1: Player!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Note, that you need to initialize the player1 variable
        player1 = Player()

    }

    @IBAction func playAudio(sender: AnyObject) {
        player1.playAudioFile()
    }
}

(在上面给出的代码中注释的文档)请设置上面的LayoutManager 到recyerview

public class CustomLayoutManager extends LinearLayoutManager {
    private static final float MILLISECONDS_PER_INCH = 50f;
    private Context mContext;

    public CustomLayoutManager(Context context) {
        super(context);
        mContext = context;
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView,
        RecyclerView.State state, final int position) {

        LinearSmoothScroller smoothScroller = 
            new LinearSmoothScroller(mContext) {

            //This controls the direction in which smoothScroll looks
            //for your view
            @Override
            public PointF computeScrollVectorForPosition
            (int targetPosition) {
                return CustomLayoutManager.this
                    .computeScrollVectorForPosition(targetPosition);
            }

            //This returns the milliseconds it takes to 
            //scroll one pixel.
            @Override
            protected float calculateSpeedPerPixel
                (DisplayMetrics displayMetrics) {
                return MILLISECONDS_PER_INCH/displayMetrics.densityDpi;
            }
        };

        smoothScroller.setTargetPosition(position);
        startSmoothScroll(smoothScroller);
    }
}

使用自定义布局管理器

  

scrollToPosition   在我的情况下你也可以使用

CustomLayoutManagerlayoutManager = new CustomLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.smoothScrollToPosition(position);

如果你想调整smoothScrollToPosition的速度,请覆盖

recyclerView.scrollToPosition(position)

在CustomLayoutManager中。 因此,如果我们将值设置为 1f ,则smoothScrollToPosition将更快,如scrollToPosition.increasing值使延迟和减少将使滚动的速度。 希望这会有用。

答案 2 :(得分:11)

就我而言,

`mRecyclerView.scrollToPosition(10);` 

也没用。 但是

`mRecyclerView.smoothScrollToPosition(10);` 

对我来说很好......

答案 3 :(得分:6)

单击EditText,从RecyclerView中的任何位置向下滚动到底部。

edittext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                rv_commentList.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                      rv_commentList.scrollToPosition(rv_commentList.getAdapter().getItemCount() - 1);
                    }
                }, 1000);
            }
        });

答案 4 :(得分:1)

尝试测量项目的宽度或高度,并调用smoothScrollBy(int dx,int dy)。

答案 5 :(得分:1)

此扩展程序非常有用,请尝试。

--spring.config.additional-location

答案 6 :(得分:1)

设备旋转后如何执行平滑滚动并保存RecyclerView垂直位置: 这是适用于我的情况的方法

public class MainFragment extends Fragment { //OR activity it's //fragment in my case
    ....
 @Override
    public void onLoadFinished(@NonNull Loader<List<Report>> loader, List<Report> objects) { // or other method of your choice, in my case it's a Loader 
    RecyclerView recyclerViewRv = findViewById(........;
         .....
    recyclerViewRv.setAdapter(.....Your adapter);

            recyclerViewRv.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                }

                @Override
                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    recyclerScrollY = recyclerViewRv. computeVerticalScrollOffset();
                }
            });

    //Apply smooth vertical scroll
    recyclerViewRv.smoothScrollBy(0,recyclerScrollY);
}
    //Save vertical scroll position before rotating devices
    @Override
        public void onSaveInstanceState(@NonNull Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putInt("recyclerScrollY",recyclerScrollY);
        }

    //BackUp vertical scroll position after rotating devices 
    @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            if(savedInstanceState != null) {
                recyclerScrollY = savedInstanceState.getInt("recyclerScrollY");
            }
        }
//If you want to perform the same operation for horizontal scrolling just add a variable called recyclerScrollX = recyclerScrollY = recyclerViewRv. computeHorizontalScrollOffset(); then save in bundle

答案 7 :(得分:0)

这些答案都不适合我。我需要 smoothScrollToPosition 但 @Ramz 回答没有用。我发现它会一直过度滚动,但只会在一个方向上滚动。我发现似乎是项目装饰者把它扔掉了。我有一个水平布局,我想在除最后一个项目之外的每个项目之后添加一个空格,但它不喜欢这种不对称性。一旦我在每个项目后面加上一个空格,它就起作用了!

答案 8 :(得分:0)

调用recyclelerView smoothScroll无效,因为recyclerView本身无法处理其布局。

您应该做的是调用布局管理器滚动方法。

这看起来应该是这样的

mRecyclerView.getLayoutManager().scrollToPosition(desiredPosition);

答案 9 :(得分:0)

因此,我一直在寻找一种解决方案,以使其在另一个具有顶部视图的布局内以recyclerview的形式返回顶部(在我的情况下,我的LinearLayout内有一个TextView和我的recyclerview)。因此,平滑滚动只能到达第一项的一半。

这是我所做的,效果很好(Kotlin解决方案):

back_to_top.setOnClickListener {
        GlobalScope.launch(Dispatchers.Main) {
            GlobalScope.launch(Dispatchers.Main) {
                recyclerview.layoutManager?.smoothScrollToPosition(recyclerview, RecyclerView.State(), 0)
                delay((recyclerview.layoutManager as LinearLayoutManager).findLastVisibleItemPosition() * 100L)
            }.join()
            recyclerview.scrollToPosition(0)
        }
        back_to_top.visibility = View.GONE
    }
}

在这里,我要平滑滚动到第一个元素,然后将滚动延迟100ms乘以最后一个可见项,然后调用scrollToPosition(0)(正确地转到顶部)

答案 10 :(得分:0)

这对我有用

    Handler().postDelayed({
                    (recyclerView.getLayoutManager() as LinearLayoutManager).scrollToPositionWithOffset( 0, 0)

}, 100)

答案 11 :(得分:0)

我遇到了一个奇怪的问题,其中 smoothScrollToPosition 仅偶尔起作用。

smoothScrollToPosition 放入 Handler Post中后 延迟,延迟时间 1秒,效果很好。

请参阅以下Kotlin示例:

Handler().postDelayed({

   recyclerViewObject.smoothScrollToPosition(0) // mention the position in place of 0

}, 1000) // 1000 indicates the 1 second delay.

答案 12 :(得分:0)

实际上,如果NestedScrollView中有RecyclerView,则每次要转到RecyclerView的开头时,都必须使用以下两行:

nestedScrollView.smoothScrollTo(0, 0);
layoutManager.scrollToPositionWithOffset(0, 0);

这完全适合我。

答案 13 :(得分:0)

任何上述解决方案均无法使用的另一个原因是,如果您的RecyclerView嵌入在NestedScrollView中。在这种情况下,您必须在NestedScrollView上调用滚动动作。

例如:

nestedScrollview.smoothScrollTo(0,0)

答案 14 :(得分:0)

recyclerView.getLayoutManager()。smoothScrollToPosition(recyclerView,new RecyclerView.State(),currentPosition);

答案 15 :(得分:0)

当您使用 scrollToPosition 时,它将显示在“回收者”视图的顶部。

但是,如果您使用 smoothScrollToPosition ,它将滚动直到它进入Window Visible。这就是为什么当SmoothScrool移到下面的项目时,它将显示在底部

答案 16 :(得分:0)

如果您想快速滚动到RecyclerView顶部的某个位置,只需使用LinearLayoutManager.scrollToPositionWithOffset(偏移量为0)即可。

示例:

mLinearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(mLinearLayoutManager);

mLinearLayoutManager.scrollToPositionWithOffset(myPosition, 0);

smoothScrollToPosition非常慢。如果您想快速进行操作,请使用scrollToPositionWithOffset。