(Smooth) ScrollToPosition не работает должным образом с RecyclerView

Я использую базовый RecyclerView с GridLayoutManager. Я заметил, что ни smoothScrollToPosition, ни scrollToPosition не работают правильно.

a) при использовании smoothScrollToPosition я часто получаю ошибку от RecyclerView

"RecyclerView: пройденное положение цели при плавной прокрутке".

и RecyclerView не прокручивается должным образом (часто он пропускает целевую строку). Это наблюдается в основном, когда я пытаюсь прокрутить до 1-го элемента некоторой строки

b) при использовании scrollToPosition он работает нормально, но большую часть времени я вижу только первый элемент строки, а остальные не отображаются.

Можете ли вы дать мне несколько советов, как правильно работать, по крайней мере, один из методов?

Спасибо большое!

Ответ 2

У меня также есть одна проблема, но мне удалось исправить проблему, настроив SmoothScroller

введите Custom LayoutManager, как показано ниже

public class CustomLayoutManager extends LinearLayoutManager {
    private static final float MILLISECONDS_PER_INCH = 50f;
    private Context mContext;

    public CustomLayoutManager(Context context) {
        super(context);
        mContext = context;
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView,
        RecyclerView.State state, final int position) {

        LinearSmoothScroller smoothScroller = 
            new LinearSmoothScroller(mContext) {

            //This controls the direction in which smoothScroll looks
            //for your view
            @Override
            public PointF computeScrollVectorForPosition
            (int targetPosition) {
                return CustomLayoutManager.this
                    .computeScrollVectorForPosition(targetPosition);
            }

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

(документация прокомментирована внутри приведенного выше кода). Установите указанный выше LayoutManager к recyerview

CustomLayoutManagerlayoutManager = new CustomLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.smoothScrollToPosition(position);

с помощью настраиваемого диспетчера макетов

scrollToPosition также хорошо работает в моем случае, вы можете использовать

recyclerView.scrollToPosition(position)

также, если вы хотите настроить скорость smoothScrollToPosition, пожалуйста, переопределите

private static final float MILLISECONDS_PER_INCH = 50f;

в CustomLayoutManager. Поэтому, если мы поместим значение как 1f, то smoothScrollToPosition будет быстрее, чем scrollToPosition.increasing значение make delay и убывание сделает скорость прокрутки. Надеюсь, это будет полезно.

Ответ 3

В моем случае

`mRecyclerView.scrollToPosition(10);` 

тоже не работает. Но

`mRecyclerView.smoothScrollToPosition(10);` 

отлично работает для меня...

Ответ 4

Чтобы прокрутить вниз до любой позиции в RecyclerView, нажмите EditText.

edittext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                rv_commentList.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                      rv_commentList.scrollToPosition(rv_commentList.getAdapter().getItemCount() - 1);
                    }
                }, 1000);
            }
        });

Ответ 5

Попробуйте измерить ширину или высоту элемента и вызовите smoothScrollBy (int dx, int dy).

Ответ 6

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

public class MainFragment extends Fragment { //OR activity it //fragment in my case
    ....
 @Override
    public void onLoadFinished(@NonNull Loader<List<Report>> loader, List<Report> objects) { // or other method of your choice, in my case it a Loader 
    RecyclerView recyclerViewRv = findViewById(........;
         .....
    recyclerViewRv.setAdapter(.....Your adapter);

            recyclerViewRv.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                }

                @Override
                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    recyclerScrollY = recyclerViewRv. computeVerticalScrollOffset();
                }
            });

    //Apply smooth vertical scroll
    recyclerViewRv.smoothScrollBy(0,recyclerScrollY);
}
    //Save vertical scroll position before rotating devices
    @Override
        public void onSaveInstanceState(@NonNull Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putInt("recyclerScrollY",recyclerScrollY);
        }

    //BackUp vertical scroll position after rotating devices 
    @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            if(savedInstanceState != null) {
                recyclerScrollY = savedInstanceState.getInt("recyclerScrollY");
            }
        }
//If you want to perform the same operation for horizontal scrolling just add a variable called recyclerScrollX = recyclerScrollY = recyclerViewRv. computeHorizontalScrollOffset(); then save in bundle

Ответ 7

Вызов recyclerView smoothScroll неэффективен, так как сам recyclerView не обрабатывает его макет.

Что вам нужно сделать, это вместо этого вызывать метод прокрутки макета менеджера.

Это должно выглядеть примерно так.

mRecyclerView.getLayoutManager().scrollToPosition(desiredPosition);

Ответ 8

Если вы пытаетесь сделать быстрый переход к позиции вверху RecyclerView, просто используйте LinearLayoutManager.scrollToPositionWithOffset со значением 0 в качестве смещения.

Пример:

mLinearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(mLinearLayoutManager);

mLinearLayoutManager.scrollToPositionWithOffset(myPosition, 0);

smoothScrollToPosition очень медленный. Если вы хотите что-то быстрое, используйте scrollToPositionWithOffset.

Ответ 9

когда вы используете scrollToPosition, он будет отображаться поверх окна рециркуляции.

Но если вы используете smoothScrollToPosition, он будет прокручиваться, пока не войдет в Window Visible. вот почему, пока smoothScrool к пункту ниже, он покажет его снизу

Ответ 10

recyclerView.getLayoutManager(). smoothScrollToPosition (recyclerView, new RecyclerView.State(), currentPosition);