Прокрутите RecyclerView, чтобы отобразить выбранный элемент сверху.

Я ищу способ прокрутки RecyclerView, чтобы показать выбранный элемент сверху.

В ListView я смог сделать это с помощью scrollTo(x,y) и получить верхнюю часть элемента, который должен быть центрирован.

Что-то вроде:

@Override
public void onItemClick(View v, int pos){
    mylistView.scrollTo(0, v.getTop());
}

Проблема заключается в том, что RecyclerView возвращает ошибку при использовании метода scrollTo, говорящего

RecyclerView не поддерживает прокрутку в абсолютную позицию

Как прокручивать RecyclerView, чтобы поместить выбранный элемент в верхнюю часть представления?

Ответ 1

Если вы используете LinearLayoutManager или Staggered GridLayoutManager, у каждого из них есть метод scrollToPositionWithOffset, который принимает как позицию, так и смещение начала элемента от начала RecyclerView, которое, по-видимому, выполнит то, что вам нужно (установив смещение до 0 должно совпадать с верхом).

Например:

//Scroll item 2 to 20 pixels from the top
linearLayoutManager.scrollToPositionWithOffset(2, 20);

Ответ 2

Если вы ищете вертикальный LinearLayout Manager, вы можете добиться плавной прокрутки с помощью пользовательского LinearSmoothScroller:

import android.content.Context;
import android.graphics.PointF;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.LinearSmoothScroller;
import android.support.v7.widget.RecyclerView;

public class SnappingLinearLayoutManager extends LinearLayoutManager {

    public SnappingLinearLayoutManager(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 SnappingLinearLayoutManager.this
                    .computeScrollVectorForPosition(targetPosition);
        }

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

используйте экземпляр layoutmanager в режиме просмотра, а затем вызов recyclerView.smoothScrollToPosition(pos); будет сглаживать прокрутку до выбранной позиции в верхней части просмотра ресайзера

Ответ 3

//Элемент прокрутки pos

linearLayoutManager.scrollToPositionWithOffset(pos, 0);

Ответ 4

Вам просто нужно позвонить recyclerview.scrollToPosition(position). Это прекрасно!

Если вы хотите вызвать его в адаптере, просто пусть ваш адаптер имеет экземпляр recyclerview или активность или фрагмент, который содержит recyclerview, чем реализует в них метод getRecyclerview().

Я надеюсь, что это может вам помочь.

Ответ 5

то же самое с регулятором скорости

public class SmoothScrollLinearLayoutManager extends LinearLayoutManager {
private static final float MILLISECONDS_PER_INCH = 110f;
private Context mContext;

public SmoothScrollLinearLayoutManager(Context context,int orientation, boolean reverseLayout) {
    super(context,orientation,reverseLayout);
    mContext = context;
}

@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
                                   int position) {
    RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext()){
        //This controls the direction in which smoothScroll looks for your view
        @Override
        public PointF computeScrollVectorForPosition(int targetPosition) {
            return new PointF(0, 1);
        }

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


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

    }

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

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

Ответ 6

Попробуйте то, что сработало для меня круто!

Создать переменную private static int displayedposition = 0;

Теперь для позиции вашего RecyclerView в вашей деятельности.

myRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                LinearLayoutManager llm = (LinearLayoutManager) myRecyclerView.getLayoutManager();


                displayedposition = llm.findFirstVisibleItemPosition();


            }
        });

Поместите этот оператор, где вы хотите, чтобы прежний сайт отображался в вашем представлении.

LinearLayoutManager llm = (LinearLayoutManager) mRecyclerView.getLayoutManager();
        llm.scrollToPositionWithOffset(displayedposition , youList.size());

Что ж, это сработало отлично для меня\o/

Ответ 7

что я сделал, чтобы восстановить положение прокрутки после обновления RecyclerView при нажатии кнопки:

if (linearLayoutManager != null) {

    index = linearLayoutManager.findFirstVisibleItemPosition();
    View v = linearLayoutManager.getChildAt(0);
    top = (v == null) ? 0 : (v.getTop() - linearLayoutManager.getPaddingTop());
    Log.d("TAG", "visible position " + " " + index);
}

else{
    index = 0;
}

linearLayoutManager = new LinearLayoutManager(getApplicationContext());
linearLayoutManager.scrollToPositionWithOffset(index, top);

получить смещение первого видимого элемента сверху до создания объекта linearLayoutManager и после его создания вызывается scrollToPositionWithOffset объекта LinearLayoutManager.

Ответ 8

прокрутка в определенном положении
 и это очень помогло мне.  через прослушиватель кликов вы можете получить позицию в своем адаптере

layoutmanager.scrollToPosition(int position);

Ответ 9

В моем случае my RecyclerView имеет верхнюю часть padding, подобную этой

<android.support.v7.widget.RecyclerView
     ...
     android:paddingTop="100dp"
     android:clipToPadding="false"
/>

Затем для прокрутки элемента вверх, мне нужно

recyclerViewLinearLayoutManager.scrollToPositionWithOffset(position, -yourRecyclerView.getPaddingTop());

Ответ 10

просто вызовите этот метод просто:

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

вместо:

recyclerView.scrollToPosition(yourItemPosition);

Ответ 11

If you want to scroll automatic without show scroll motion then you need to write following code:

**=> mRecyclerView.getLayoutManager().scrollToPosition(position);**

If you want to display scroll motion then you need to add following code.
=>Step 1: You need to declare SmoothScroller.

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

=>step 2: You need to add this code any event you want to perform scroll to specific position.
=>First you need to set target position to SmoothScroller.

**smoothScroller.setTargetPosition(position);**

=>Then you need to set SmoothScroller to LayoutManager.
                        **mRecyclerView.getLayoutManager().startSmoothScroll(smoothScroller);**

Ответ 12

Я не знаю, почему я не нашел лучший ответ, но это действительно просто.

recyclerView.smoothScrollToPosition(position);

Нет ошибок

Создает анимацию

Ответ 13

Предупреждение для особого случая:

Все эти методы плавной прокрутки не работали вообще в моем приложении. Системная библиотека явно не соответствует спецификации Google. На самом деле список иногда прокручивается, но затем на произвольную позицию, а не на ту, на которую он должен был рассчитывать.

У меня есть подозрение, что библиотека слишком тупая. Каждая из моих строк имеет свою индивидуальную высоту, которая рассчитывается во время выполнения, т.е. Не перед созданием представления элемента. Таким образом, чтобы найти правильную позицию, библиотека должна создать представление каждой строки вплоть до запрошенной. Но, очевидно, это не так. Вот почему я изначально использовал старый добрый ListView и метод smoothScrollToPosition(). Это сработало.

Ответ 14

Я использую приведенный ниже код для плавного прокрутки элемента (thisView) до вершины.
Он также работает для GridLayoutManager с представлениями разной высоты:

View firstView = mRecyclerView.getChildAt(0);
int toY = firstView.getTop();
int firstPosition = mRecyclerView.getChildAdapterPosition(firstView);
View thisView = mRecyclerView.getChildAt(thisPosition - firstPosition);
int fromY = thisView.getTop();

mRecyclerView.smoothScrollBy(0, fromY - toY);

Кажется, он работает достаточно хорошо для быстрого решения.