web-dev-qa-db-ja.com

(Smooth)ScrollToPositionはRecyclerViewで適切に動作しません

GridLayoutManagerで基本的なRecyclerViewを使用しています。また、smoothScrollToPositionもscrollToPositionも適切に機能することを確認しました。

a)smoothScrollToPositionを使用しているとき、RecyclerViewからエラーを受け取ることがよくあります

「RecyclerView:は、スムーズなスクロール中に目標位置を通過しました。」

およびRecyclerViewが適切にスクロールされません(多くの場合、対象の行を見逃します)。これは主に、ある行の最初のアイテムにスクロールしようとするときに観察されます

b)scrollToPositionを使用する場合、かなりうまくいくようですが、ほとんどの場合、行の最初の項目のみが表示され、残りは表示されません。

少なくとも1つの方法を適切に機能させるためのヒントを教えてください。

どうもありがとう!

45
petrushka1986

最終的に私はそれを機能させることができました! LinearLayoutManager.scrollToPositionWithOffset(int, int) トリックをしました。

60
petrushka1986

私も同じ問題を抱えていますが、SmoothScrollerをカスタマイズすることで問題を解決できました

以下のようにカスタムLayoutManagerをしましょう

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);
    }
}

(上記のコード内でコメントされているドキュメント)上記のLayoutManagerをrecyerviewに設定してください

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

カスタムレイアウトマネージャーを使用して

scrollToPositionも私の場合はうまく機能しています

recyclerView.scrollToPosition(position)

また、smoothScrollToPositionの速度を調整する場合は、

private static final float MILLISECONDS_PER_INCH = 50f;

customLayoutManagerで。したがって、値を1fとして設定すると、smoothScrollToPositionはscrollToPosition.increasing値が遅延を遅らせ、減少がスクロールの速度を上げるように高速になります。これが役に立つことを願っています。

14
Ramz

私の場合、

`mRecyclerView.scrollToPosition(10);` 

また動作しませんでした。しかし

`mRecyclerView.smoothScrollToPosition(10);` 

私にとってはうまくいきます...

12
zephyr

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);
            }
        });

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

1
J.Sattar

スムーズなスクロールを実行し、デバイスの回転後に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
1
Ahmed KHABER

アイテムの幅または高さを測定して、smoothScrollBy(int dx、int dy)を呼び出してください。

1
Dubrovin

scrollToPositionを使用すると、リサイクラビューの上部に表示されます。

ただし、smoothScrollToPositionを使用すると、Window Visibleに入るまでスクロールします。そのため、smoothScroolを下のアイテムにすると、下に表示されます

0
Chiam Simon V

RecyclerViewの上部の位置にクイックスクロールを実行する場合は、LinearLayoutManager.scrollToPositionWithOffsetを0をオフセットとして使用するだけです。

例:

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

mLinearLayoutManager.scrollToPositionWithOffset(myPosition, 0);

smoothScrollToPositionは非常に遅いです。 scrollToPositionWithOffsetを使用すると、高速で何かを実行できます。

0
live-love

RecyclerView自体はそのレイアウトを処理しないため、recyclerView smoothScrollを呼び出すことは効果的ではありません。

代わりに、レイアウトマネージャーのscrollメソッドを呼び出してください。

これは次のようになります

mRecyclerView.getLayoutManager().scrollToPosition(desiredPosition);
0
orelzion