ПРИХОДИТЕ УЧИТЬСЯ НОВОЙ ПРОФЕССИИ ЛЕТОМ СО СКИДКОЙ ДО 70%Забронировать скидку

Прокрутка до конца списка RecyclerView: настройка scrollToPosition

Пройдите тест, узнайте какой профессии подходите и получите бесплатную карьерную консультацию
В конце подарим скидку до 55% на обучение
Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Если хочется без задержек прокрутить до конца RecyclerView, воспользуйтесь методом layoutManager.scrollToPositionWithOffset, предварительно передав в него индекс последнего элемента списка. Такой метод обеспечивает моментальный переход, без лишней анимации:

Java
Скопировать код
// Получаем LayoutManager
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
// Определение индекса последнего элемента (учитывая, что нумерация идет с нуля)
int lastPosition = recyclerView.getAdapter().getItemCount() – 1;
// Прокрутка до конца 
layoutManager.scrollToPositionWithOffset(lastPosition, 0);

Применяйте предложенный код после загрузки данных в адаптер RecyclerView или после их обновления.

Пройдите тест и узнайте подходит ли вам сфера IT
Пройти тест

Отложенное выполнение операции прокрутки

Если метод scrollToPosition не приводит к ожидаемому результату, это может быть связано с незавершенной инициализацией RecyclerView. Чтобы гарантировать исправную прокрутку после завершения инициализации, можно отложить события, связанные с прокруткой:

Java
Скопировать код
recyclerView.post(new Runnable() {
    @Override
    public void run() {
        // Мгновенная прокрутка к последнему элементу
        recyclerView.scrollToPosition(adapter.getItemCount() – 1);
    }
});

Плавная прокрутка

Для поднятия комфортности пользовательского опыта можно добавить анимацию для плавной прокрутки. Для этого свойственно заменить scrollToPosition на smoothScrollToPosition:

Java
Скопировать код
// Прокрутка становится плавной, подобно капле топленого масла, разливающейся по горячему тосту
recyclerView.smoothScrollToPosition(adapter.getItemCount() – 1);

Работа с обратной ориентацией макета

Если прорабатывается обратный порядок расположения элементов в RecyclerView, то настройте LinearLayoutManager следующим образом:

Java
Скопировать код
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
linearLayoutManager.setReverseLayout(true); // Элементы будут располагаться снизу вверх
linearLayoutManager.setStackFromEnd(true);  // Стек элементов начинается с конца списка
recyclerView.setLayoutManager(linearLayoutManager);

Визуализация

Можно представить процесс прокрутки до конца списка в RecyclerView как вызов лифта в высотном здании:

До: 🏢[👨‍👩‍👧‍👦📈🛒(Вы находитесь здесь)] <- Первый этаж
После: 🏢[🛒(Вы прибыли)📉👨‍👩‍👧‍👦] <- Последний этаж

Чтобы оказаться на "последнем этаже" (то есть в конце списка), вызовите scrollToPosition с индексом последнего элемента:

Java
Скопировать код
// Взлетаем на последний этаж!
recyclerView.scrollToPosition(adapter.getItemCount() – 1);

Убедитесь, что метод вызывается только после инициализации RecyclerView.

Согласование с изменениями данных

Отражение прокрутки после обновления данных

После обновления данных в адаптере, не забывайте вызывать метод notifyDataSetChanged или подобный ему, чтобы RecyclerView смог обнаружить изменения данных и выполнить прокрутку:

Java
Скопировать код
// Информируем о новых данных
adapter.notifyDataSetChanged();
// Переходим к последнему элементу обновленного списка
recyclerView.scrollToPosition(adapter.getItemCount() – 1);

Взаимодействие с динамическим контентом

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

Java
Скопировать код
recyclerView.getAdapter().registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
    @Override
    public void onItemRangeInserted(int positionStart, int itemCount) {
        super.onItemRangeInserted(positionStart, itemCount);
        int totalItemCount = recyclerView.getLayoutManager().getItemCount();
        int lastVisiblePosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findLastCompletelyVisibleItemPosition();

        // Если мы в начале списка или нам нужно перейти к новым сообщениям
        if (lastVisiblePosition == -1 ||
                (positionStart >= (totalItemCount – 1) && lastVisiblePosition == (positionStart – 1)) {
            recyclerView.scrollToPosition(positionStart);
        }
    }
});

Как избегать lurking pitfalls

  1. Ожидайте окончания инициализации: Прокрутка до момента готовности RecyclerView к использованию поможет избежать ошибок.
  2. Не забывайте о нулевом индексе: Всегда отнимайте 1 при использовании getItemCount(), учтя нумерацию элементов начиная с нуля.
  3. Предотвратите вложенную прокрутку: Прокрутка внутри других прокручиваемых элементов часто ведет к ошибкам. Желательно избегать вложения RecyclerView в ScrollView или NestedScrollView, или же неактивировать прокрутку для внешнего элемента, обладающего свойством прокрутки.

Полезные материалы

  1. RecyclerView | Android Developers – ещё общий обзор метода scrollToPosition в RecyclerView на официальной документации.
  2. Проблемы RecyclerView в ScrollView – Stack Overflow – на примере обсуждения на сообществе Stack Overflow изложенные проблемы с прокруткой в RecyclerView.
  3. Изучаем RecyclerView на Android – Medium – статья подробно рассматривает возможности RecyclerView, включая прокрутку.
  4. Плавная прокрутка в RecyclerView – ProAndroidDev – пошаговое руководство по реализации плавной прокрутки в RecyclerView.
  5. LinearSmoothScroller | Android Developers – полное руководство для разработчиков по LinearSmoothScroller для плавной прокрутки в RecyclerView.
  6. Туториал по прокрутке в RecyclerView | CodePath Android Cliffnotes – полезное руководство по программной прокрутке RecyclerView.
  7. Обзор RecyclerView на Android | Grokking Android – статья с важными советами и лучшими практиками по использованию RecyclerView.