web-dev-qa-db-ja.com

RecyclerView-特定の位置でアイテムの上部までスムーズにスクロールする方法は?

RecyclerViewで、選択したアイテムの上部に突然スクロールすることができます:

((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(position, 0);

ただし、これは突然アイテムを最上部に移動します。アイテムの上に移動したいsmoothly.

私も試しました:

recyclerView.smoothScrollToPosition(position);

ただし、一番上に選択した位置にアイテムを移動しないため、うまく機能しません。その位置のアイテムが表示されるまで、リストを単にスクロールします。

89
Tiago

RecyclerViewは拡張可能に設計されているため、スクロールを実行するためだけにLayoutManagerをサブクラス化する必要はありません( droidev推奨 )。

代わりに、設定SNAP_TO_STARTSmoothScrollerを作成するだけです:

RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(context) {
  @Override protected int getVerticalSnapPreference() {
    return LinearSmoothScroller.SNAP_TO_START;
  }
};

次に、スクロールする位置を設定します。

smoothScroller.setTargetPosition(position);

そのSmoothScrollerをLayoutManagerに渡します。

layoutManager.startSmoothScroll(smoothScroller);
155
Paul Woitaschek

このためには、カスタムLayoutManagerを作成する必要があります

public class LinearLayoutManagerWithSmoothScroller extends LinearLayoutManager {

    public LinearLayoutManagerWithSmoothScroller(Context context) {
        super(context, VERTICAL, false);
    }

    public LinearLayoutManagerWithSmoothScroller(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
                                       int position) {
        RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext());
        smoothScroller.setTargetPosition(position);
        startSmoothScroll(smoothScroller);
    }

    private class TopSnappedSmoothScroller extends LinearSmoothScroller {
        public TopSnappedSmoothScroller(Context context) {
            super(context);

        }

        @Override
        public PointF computeScrollVectorForPosition(int targetPosition) {
            return LinearLayoutManagerWithSmoothScroller.this
                    .computeScrollVectorForPosition(targetPosition);
        }

        @Override
        protected int getVerticalSnapPreference() {
            return SNAP_TO_START;
        }
    }
}

これをご使用のRecyclerViewに使用し、smoothScrollToPositionを呼び出します。

例:

 recyclerView.setLayoutManager(new LinearLayoutManagerWithSmoothScroller(context));
 recyclerView.smoothScrollToPosition(position);

これにより、指定した位置のRecyclerViewアイテムの上部にスクロールします。

お役に立てれば。

103
droidev

このように試すことができます

    recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView,new RecyclerView.State(), recyclerView.getAdapter().getItemCount());
6
Supto

これは、RecyclerViewで直接呼び出すためにKotlinで記述した拡張関数です(@Paul Woitaschekの回答に基づきます)。

fun RecyclerView.smoothSnapToPosition(position: Int, snapMode: Int = LinearSmoothScroller.SNAP_TO_START) {
    val smoothScroller = object: LinearSmoothScroller(this.context) {
        override fun getVerticalSnapPreference(): Int {
            return snapMode
        }

        override fun getHorizontalSnapPreference(): Int {
            return snapMode
        }
    }
    smoothScroller.targetPosition = position
    layoutManager?.startSmoothScroll(smoothScroller)
}

次のように使用します。

myRecyclerView.smoothSnapToPosition(itemPosition)
4
vovahost

RecyclerViewをスクロールする最も簡単な方法は、次のとおりです。

// Define the Index we wish to scroll to.
final int lIndex = 0;
// Assign the RecyclerView's LayoutManager.
this.getRecyclerView().setLayoutManager(this.getLinearLayoutManager());
// Scroll the RecyclerView to the Index.
this.getLinearLayoutManager().smoothScrollToPosition(this.getRecyclerView(), new RecyclerView.State(), lIndex);
3
Mapsy

私はこのように使用しました:

recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView, new RecyclerView.State(), 5);
1
Criss

LinearSmoothScrollerのCalculateDyToMakeVisible/calculateDxToMakeVisible関数をオーバーライドして、オフセットY/X位置を実装します

override fun calculateDyToMakeVisible(view: View, snapPreference: Int): Int {
    return super.calculateDyToMakeVisible(view, snapPreference) - ConvertUtils.dp2px(10f)
}
1
user2526517

おそらく@droidevのアプローチが正しい方法ですが、基本的に同じ仕事をし、LayoutManagerの拡張を必要としない、少し異なるものを公開したいだけです。

ここ-これは、アイテム(リストの一番上でスクロールしたいアイテム)が画面に表示されていて、自動的に一番上までスクロールしたい場合にうまく機能します。リストの最後のアイテムに何らかのアクションがあり、同じリストに新しいアイテムを追加し、新しく追加したアイテムにユーザーを集中させたい場合に便利です。

int recyclerViewTop = recyclerView.getTop();
int positionTop = recyclerView.findViewHolderForAdapterPosition(positionToScroll) != null ? recyclerView.findViewHolderForAdapterPosition(positionToScroll).itemView.getTop() : 200;
final int calcOffset = positionTop - recyclerViewTop; 
//then the actual scroll is gonna happen with (x offset = 0) and (y offset = calcOffset)
recyclerView.scrollBy(0, offset);

アイデアは簡単です。1. recyclerview要素の最上位座標を取得する必要があります。 2.一番上までスクロールするビューアイテムの一番上の座標を取得する必要があります。 3.最後に、計算されたオフセットで行う必要があります

recyclerView.scrollBy(0, offset);

200は、ハードウェアでコーディングされた整数値の単なる例であり、ビューホルダーアイテムが存在しない場合に使用できます。

0
Sniper