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

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

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

что-то типа:

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

проблема в том, что RecyclerView возвращает ошибку при использовании это scrollTo способ сказать

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

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

12 ответов


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

например:

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

Если вы ищете вертикальный 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 в представлении recycle, а затем вызовите recyclerView.smoothScrollToPosition(pos); сгладит прокрутку до выбранной позиции в верхней части представления recycler


/ / прокрутить пункт pos

linearLayoutManager.scrollToPositionWithOffset(pos, 0);

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

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

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


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

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

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

создать переменную 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/


что я сделал, чтобы восстановить положение прокрутки после обновления 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.


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

layoutmanager.scrollToPosition(int position);

В моем случае мой RecyclerView есть отступ сверху такой

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

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

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

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

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

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

вместо:

RecyclerView.scrollToPosition(yourItemPosition);

Я использую код ниже, чтобы плавно прокрутить элемент (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);

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