Прокрутка до конца списка RecyclerView: настройка scrollToPosition
Быстрый ответ
Если хочется без задержек прокрутить до конца RecyclerView, воспользуйтесь методом layoutManager.scrollToPositionWithOffset
, предварительно передав в него индекс последнего элемента списка. Такой метод обеспечивает моментальный переход, без лишней анимации:
// Получаем LayoutManager
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
// Определение индекса последнего элемента (учитывая, что нумерация идет с нуля)
int lastPosition = recyclerView.getAdapter().getItemCount() – 1;
// Прокрутка до конца
layoutManager.scrollToPositionWithOffset(lastPosition, 0);
Применяйте предложенный код после загрузки данных в адаптер RecyclerView или после их обновления.
Отложенное выполнение операции прокрутки
Если метод scrollToPosition
не приводит к ожидаемому результату, это может быть связано с незавершенной инициализацией RecyclerView. Чтобы гарантировать исправную прокрутку после завершения инициализации, можно отложить события, связанные с прокруткой:
recyclerView.post(new Runnable() {
@Override
public void run() {
// Мгновенная прокрутка к последнему элементу
recyclerView.scrollToPosition(adapter.getItemCount() – 1);
}
});
Плавная прокрутка
Для поднятия комфортности пользовательского опыта можно добавить анимацию для плавной прокрутки. Для этого свойственно заменить scrollToPosition
на smoothScrollToPosition
:
// Прокрутка становится плавной, подобно капле топленого масла, разливающейся по горячему тосту
recyclerView.smoothScrollToPosition(adapter.getItemCount() – 1);
Работа с обратной ориентацией макета
Если прорабатывается обратный порядок расположения элементов в RecyclerView, то настройте LinearLayoutManager
следующим образом:
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
linearLayoutManager.setReverseLayout(true); // Элементы будут располагаться снизу вверх
linearLayoutManager.setStackFromEnd(true); // Стек элементов начинается с конца списка
recyclerView.setLayoutManager(linearLayoutManager);
Визуализация
Можно представить процесс прокрутки до конца списка в RecyclerView как вызов лифта в высотном здании:
До: 🏢[👨👩👧👦📈🛒(Вы находитесь здесь)] <- Первый этаж
После: 🏢[🛒(Вы прибыли)📉👨👩👧👦] <- Последний этаж
Чтобы оказаться на "последнем этаже" (то есть в конце списка), вызовите scrollToPosition
с индексом последнего элемента:
// Взлетаем на последний этаж!
recyclerView.scrollToPosition(adapter.getItemCount() – 1);
Убедитесь, что метод вызывается только после инициализации RecyclerView.
Согласование с изменениями данных
Отражение прокрутки после обновления данных
После обновления данных в адаптере, не забывайте вызывать метод notifyDataSetChanged
или подобный ему, чтобы RecyclerView смог обнаружить изменения данных и выполнить прокрутку:
// Информируем о новых данных
adapter.notifyDataSetChanged();
// Переходим к последнему элементу обновленного списка
recyclerView.scrollToPosition(adapter.getItemCount() – 1);
Взаимодействие с динамическим контентом
В случае динамического контента, например, в чат-приложениях, для того чтобы удержать список в нижнем положении при появлении новых сообщений, используйте AdapterDataObserver
:
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
- Ожидайте окончания инициализации: Прокрутка до момента готовности RecyclerView к использованию поможет избежать ошибок.
- Не забывайте о нулевом индексе: Всегда отнимайте
1
при использованииgetItemCount()
, учтя нумерацию элементов начиная с нуля. - Предотвратите вложенную прокрутку: Прокрутка внутри других прокручиваемых элементов часто ведет к ошибкам. Желательно избегать вложения RecyclerView в
ScrollView
илиNestedScrollView
, или же неактивировать прокрутку для внешнего элемента, обладающего свойством прокрутки.
Полезные материалы
- RecyclerView | Android Developers – ещё общий обзор метода
scrollToPosition
в RecyclerView на официальной документации. - Проблемы RecyclerView в ScrollView – Stack Overflow – на примере обсуждения на сообществе Stack Overflow изложенные проблемы с прокруткой в RecyclerView.
- Изучаем RecyclerView на Android – Medium – статья подробно рассматривает возможности RecyclerView, включая прокрутку.
- Плавная прокрутка в RecyclerView – ProAndroidDev – пошаговое руководство по реализации плавной прокрутки в RecyclerView.
- LinearSmoothScroller | Android Developers – полное руководство для разработчиков по LinearSmoothScroller для плавной прокрутки в RecyclerView.
- Туториал по прокрутке в RecyclerView | CodePath Android Cliffnotes – полезное руководство по программной прокрутке RecyclerView.
- Обзор RecyclerView на Android | Grokking Android – статья с важными советами и лучшими практиками по использованию RecyclerView.