Подтвердить что ты не робот

RecyclerView - Как сгладить прокрутку до вершины позиции на определенной позиции?

В RecyclerView я могу неожиданно прокрутить до вершины выбранного элемента, используя:

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

Однако это резко перемещает элемент в верхнее положение. Я хочу перейти в верхнюю часть элемента плавно.

Я также пробовал:

recyclerView.smoothScrollToPosition(position);

но он не работает хорошо, так как он не перемещает элемент в позицию, выбранную вверху. Он просто прокручивает список, пока элемент в позиции не будет виден.

4b9b3361

Ответ 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 - это просто пример целочисленного целочисленного значения, которое вы можете использовать, если элемент держателя не существует, потому что это также возможно.