RecyclerView - Как сгладить прокрутку до вершины позиции на определенной позиции?
В RecyclerView я могу неожиданно прокрутить до вершины выбранного элемента, используя:
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(position, 0);
Однако это резко перемещает элемент в верхнее положение. Я хочу перейти в верхнюю часть элемента плавно.
Я также пробовал:
recyclerView.smoothScrollToPosition(position);
но он не работает хорошо, так как он не перемещает элемент в позицию, выбранную вверху. Он просто прокручивает список, пока элемент в позиции не будет виден.
Ответы
Ответ 1
RecyclerView
предназначен для расширения, поэтому нет необходимости подклассифицировать LayoutManager
(как droidev предложил), чтобы выполнить прокрутку.
Вместо этого просто создайте SmoothScroller
с предпочтением SNAP_TO_START
:
RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(context) {
@Override protected int getVerticalSnapPreference() {
return LinearSmoothScroller.SNAP_TO_START;
}
};
Теперь вы устанавливаете положение, в котором вы хотите прокрутить до:
smoothScroller.setTargetPosition(position);
и передать этот SmoothScroller в LayoutManager:
layoutManager.startSmoothScroll(smoothScroller);
Ответ 2
для этого вам нужно создать собственный 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 указанной позиции.
надеюсь, что это поможет.
Ответ 3
Мы можем попробовать вот так
recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView,new RecyclerView.State(), recyclerView.getAdapter().getItemCount());
Ответ 4
Это расширение функций, которые я написал в Kotlin для вызова непосредственно в RecyclerView (на основе ответа @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)
Ответ 5
Самый простой способ, которым я нашел прокрутку RecyclerView
, выглядит следующим образом:
// Define the Index we wish to scroll to.
final int lIndex = 0;
// Assign the RecyclerView LayoutManager.
this.getRecyclerView().setLayoutManager(this.getLinearLayoutManager());
// Scroll the RecyclerView to the Index.
this.getLinearLayoutManager().smoothScrollToPosition(this.getRecyclerView(), new RecyclerView.State(), lIndex);
Ответ 6
Переопределите функцию CalculateDyToMakeVisible/CalculateDxToMakeVisible в LinearSmoothScroller, чтобы реализовать позицию смещения Y/X
override fun calculateDyToMakeVisible(view: View, snapPreference: Int): Int {
return super.calculateDyToMakeVisible(view, snapPreference) - ConvertUtils.dp2px(10f)
}
Ответ 7
Я использовал как это:
recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView, new RecyclerView.State(), 5);
Ответ 8
Вероятно, подход @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 - это просто пример целочисленного целочисленного значения, которое вы можете использовать, если элемент держателя не существует, потому что это также возможно.