Как сделать прокрутку RecyclerView плавно?

Это больше похоже на общий вопрос, но после долгих поисков и попыток я не могу понять, почему этого так трудно достичь. этой - самый близкий ответ, который я могу найти, но все еще не могу реализовать.

чтобы быть конкретным, я использую RecyclerView с GridLayoutManager. Все ,что я хочу, это макет сетки для плавной прокрутки (например, приложение по умолчанию gallary), ничего необычного, но реализация по умолчанию менеджера макета сетки прокручивает представление "рывками". Я пытался реализовать метод сверху link, но безуспешно.

Я также попытался реализовать LinearSmoothScroller, но я не уверен, как реализовать метод computeScrollVectorForPosition. документация Google на computeScrollVectorForPosition буквально имеет 0 слов.

нашел это 3 часть учебника, но это было очень мало. Итак, все хочу спросить: Может ли быть какой-то код шаблона, который мы можем реализовать в LinearSmoothScroller или путем расширения RecyclerView.SmoothScroller и добиться плавной прокрутки ? Даже если код зависит от количества элементов и элементов в строке в gridlayout, должен быть какой-то метод, чтобы сделать это легко. Я что-то упускаю ?

7 ответов


типичным источником" отрывистой " прокрутки в Android является приложение, занимающее слишком много времени на главном потоке приложения, обновляющем пользовательский интерфейс. В случае RecyclerView, Это означало бы слишком много времени в onBindViewHolder() или, возможно, в onCreateViewHolder(). Каждый из них должен вернуться в субмиллисекундные времена, то есть вы не можете сделать дисковый ввод-вывод или сетевой ввод-вывод в них.

думаю, я нашел проблему. Я использую держатель.фотография.setImageBitmap(BitmapFactory.decodeFile(itemList.get (позиция).getAbsolutePath ())); on onBindViewHolder () и файл изображения составляет около 100 КБ каждый с примерно десятком изображений в списке

Да, это будет делать дисковый ввод-вывод и декодирование изображений в основном потоке приложения. Это будет достаточно медленно, чтобы вызвать jank в пользовательском интерфейсе (т. е. "отрывистую" прокрутку).

рассмотрите возможность использования библиотеки загрузки изображений, например Picasso или Universal Image Loader, как они могут заполнить ImageView из растрового изображения асинхронно.

этот пример приложения использует универсальный загрузчик изображений, чтобы помочь заполнить содержимое RecyclerViewGridLayoutManager), причем источником данных являются доступные видео на устройстве.


добавить это везде, где вы объявили RecyclerView в своем Activity или Fragment

RecyclerView mRecyclerview = (RecyclerView) findViewById(...);
mRecyclerview.setNestedScrollingEnabled(false);

setNestedScrollview(false) делает работу за вас.


Я просто столкнулся с этой проблемой, и отключение вложенной прокрутки исправило ее. Сделайте это так:

yourRecyclerview.setNestedScrollingEnabled(false);

или вы можете изменить значение в xml-файле, где вы определили RecyclerView:

<android.support.v7.widget.RecyclerView
    android:id="@+id/yourRecyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:nestedScrollingEnabled="false"/>

android:animateLayoutChanges="false"

Я просто столкнулась с этой проблемой, и я получил Я поставил RecyclerView на ScrollView Поэтому, пожалуйста, никогда не ставьте RecyclerView внутри ScrollView что также может вызвать.

mLayoutManager.findFirstVisibleItemPosition()

это всегда возвращает фиксированное значение. А также проверить

recyclerview.setNestedScrollingEnabled(false);

Я сделал прокрутку гладкой, переопределив calculateSpeedPerPixel(DisplayMetrics displayMetrics) способ:

public class CustomLayoutManager extends LinearLayoutManager {

    protected CenterLayoutManager(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 CenterSmoothScroller(recyclerView.getContext());
        smoothScroller.setTargetPosition(position);
        startSmoothScroll(smoothScroller);
    }

    private class CenterSmoothScroller extends LinearSmoothScroller {

        CenterSmoothScroller(Context context) {
            super(context);
        }

        @Override
        public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
            return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
        }

        @Override
        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
            return 0.5f; //pass as per your requirement
        }
    }
}

просто добавить этот

animateLayoutChanges = true 

в recyclerview в XML