Android studio recyclerview прокрутить до элемента

RecyclerView

Компонент RecyclerView появился в Android 5.0 Lollipop и находится в разделе Containers. Для простоты буду называть его списком, хотя на самом деле это универсальный элемент управления с большими возможностями.

Раньше для отображения прокручиваемого списка использовался ListView. Со временем у него обнаружилось множество недостатков, которые было трудно исправить. Тогда решили создать новый элемент с нуля.

Вначале это был сырой продукт, потом его доработали. На данном этапе можно считать, что он стал полноценной заменой устаревшего ListView.

Схематично работу RecyclerView можно представить следующим образом. На экране отображаются видимые элементы списка. Когда при прокрутке списка верхний элемент уходит за пределы экрана и становится невидимым, его содержимое очищается. При этом сам «чистый» элемент помещается вниз экрана и заполняется новыми данными, иными словами переиспользуется, отсюда название Recycle.

Компонент RecyclerView не является родственником ListView и относится к семейству ViewGroup. Он часто используется как замена ListView, но его возможности шире.

Следует сказать, что при работе с ним приходится писать много кода, который пугает новичков. Если с RecyclerView работать не постоянно, то порой забываются детали и сложно вспомнить необходимые шаги. Многие просто сохраняют отдельные шаблоны и копируют в разные проекты.

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

Для размещения своих дочерних элементов используется специальный менеджер макетов LayoutManager. Он может быть трёх видов.

  • LinearLayoutManager — дочерние элементы размещаются вертикально (как в ListView) или горизонтально
  • GridLayoutManager — дочерние элементы размещаются в сетке, как в GridView
  • StaggeredGridLayoutManager — неравномерная сетка

Можно создать собственный менеджер на основе RecyclerView.LayoutManager.

RecyclerView.ItemDecoration позволяет работать с дочерними элементами: отступы, внешний вид.

ItemAnimator — отвечает за анимацию элементов при добавлении, удалении и других операций.

RecyclerView.Adapter связывает данные с компонентом и отслеживает изменения.

  • notifyItemInserted(), notifyItemRemoved(), notifyItemChanged() — методы, отслеживающие добавление, удаление или изменение позиции одного элемента
  • notifyItemRangeInserted(), notifyItemRangeRemoved(), notifyItemRangeChanged() — методы, отслеживающие изменение порядка элеметов

Стандартный метод notifyDataSetChanged() поддерживается, но он не приводит к внешнему изменению элементов на экране.

Программисты со стажем знают, что для создания «правильного» ListView нужно было создавать класс ViewHolder. В старых списках его можно было игнорировать. Теперь это стало необходимым условием.

Общая модель работы компонента.

Мы рассмотрим только базовый пример для быстрого знакомства. В реальных проектах примеры будут гораздо сложнее, чтобы обеспечить другие функциональные возможности — обработка жестов, анимация, динамическое удаление и добавление элементов.

Размещаем компонент в макете экрана через панель инструментов. Но сначала добавим зависимость.

Создадим макет для отдельного элемента списка. Варианты могут быть самыми разными — можно использовать один TextView для отображения строк (имена котов), можно использовать связку ImageView и TextView (имена котов и их наглые морды). Мы возьмём для примера две текстовые метки. Создадим новый файл res/layout/recyclerview_item.xml.

Читайте также:  Не удается скопировать элемент устройство перестало отвечать или было отключено android

Добавим компонент в разметку экрана активности.

Минимальный код для запуска.

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

Начнём по порядку, чтобы запомнить последовательность. Для начала создадим обычный класс и в конструкторе передадим список строк. Список будет содержать имена котов.

Класс MyViewHolder на основе ViewHolder служит для оптимизации ресурсов. Новый класс добавим в состав нашего созданного ранее класса.

В созданном классе нужно просто перечислить используемые компоненты из макета для отдельного элемента списка. В нашем примере задействованы два TextView, инициализируем их через идентификаторы.

Создадим адаптер — наследуем наш класс от класса RecyclerView.Adapter и в качестве параметра указываем созданный нами MyViewHolder. Студия попросит реализовать три метода.

getItemCount()

Как правило данные являются однотипными, например, список или массив строк. Адаптеру нужно знать, сколько элементов нужно предоставить компоненту, чтобы распределить ресурсы и подготовиться к отображению на экране. При работе с коллекциями или массивом мы можем просто вычислить его длину и передать это значение методу адаптера getItemCount(). В простых случаях мы можем записать код в одну строчку.

onCreateViewHolder

В методе onCreateViewHolder нужно указать идентификатор макета для отдельного элемента списка, созданный нами ранее в файле recyclerview_item.xml. А также вернуть наш объект класса ViewHolder.

onBindViewHolder()

В методе адаптера onBindViewHolder() связываем используемые текстовые метки с данными — в одном случае это значения из списка, во втором используется одна и та же строка.

Должно получиться следующее.

Подключаем в активности. Создадим пока бессмысленный список строк, который передадим в адаптер.

Запускаем ещё раз.

Вариант с числами нам не интересен, поэтому добавим котов. Имена котов и кошек разместим в ресурсах в виде массива в файле res/values/strings.xml.

Создадим новую функцию для получения списка котов из ресурсов и передадим его адаптеру.

Горизонтальная прокрутка

Можем указать горизонтальный вариант прокрутки. Остальной код менять не придётся.

А можно вообще обойтись только XML-декларацией.

Оптимизация

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

При работе с изображениями старайтесь использовать готовые библиотеки Picasso, Glide, Fresco и т.д.

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

Не перегружайте лишним кодом метод onBindViewHolder(). Только самое необходимое.

Источник

Как сохранить позицию прокрутки RecyclerView в Android?

У меня есть представление Recycler, которое находится внутри SwipeRefreshLayout. Кроме того, у вас есть возможность открывать каждый элемент в другом действии. После возврата в Recycler мне нужно прокрутить до выбранного элемента или до предыдущего Y. Как это сделать?

Да, я погуглил, нашел в StackOverFlow статьи о сохранении экземпляра диспетчера компоновки, например этот: RecyclerView сохраняет / восстанавливает состояние между действиями. Но мне это не помогает.

Читайте также:  Humax cxhd 5150c прошивка android

ОБНОВЛЕНИЕ

Сейчас у меня есть такая решающая проблема, но, конечно, тоже не работает.

Да, я пробовал scrollTo (int, int) — не работает.

Теперь я попробовал просто прокрутить, например, до Y = 100, но прокрутки нет вообще.

8 ответов

Сохраните текущее состояние позиции повторного просмотра @onPause:

Восстановить позицию прокрутки @onResume:

Или другим способом может быть @onPause:

По какой-то причине существует множество вводящих в заблуждение советов / предложений о том, как сохранять и восстанавливать положение прокрутки в your_scrolling_container при изменении ориентации.

Взять текущую позицию прокрутки и сохранить ее в onSaveInstanceState Activity. Расширение определенного прокручиваемого View, чтобы сделать то же самое. Предотвращение разрушения Activity при вращении. И да, они работают нормально, но .

Но на самом деле все намного проще, потому что Android уже делает это за вас!

Если вы внимательно посмотрите на источники RecyclerView / ListView / ScrollView / NestedScrollView, вы увидите, что каждый из них сохраняет свою позицию прокрутки в onSaveInstanceState. И во время первого прохода макета они пытаются прокрутить до этой позиции в методе onLayout.

Чтобы убедиться, что все работает нормально, вам нужно сделать всего 2 вещи:

Установите идентификатор для прокручиваемого представления, что, вероятно, уже сделано. В противном случае Android не сможет автоматически сохранять состояние просмотра.

Предоставьте данные перед первым проходом макета, чтобы иметь те же границы прокрутки, которые были перед вращением. На этом этапе у разработчиков обычно возникают проблемы.

Самый простой и совместимый с переходом способ, который я нашел:

Используйте свой ресайклер для просмотра linearlayoutmanager для получения позиции прокрутки

И при восстановлении используйте следующий код

Надеюсь, это поможет тебе

Вы можете использовать scrollToPosition или smoothScrollToPosition для перехода к любой позиции элемента в RecyclerView .

Если вы хотите прокрутить до позиции элемента в адаптере , вам придется использовать адаптер scrollToPosition или smoothScrollToPosition .

Чтобы сохранить позицию в настройках, добавьте это в свой onStop ()

Затем восстановите положение, подобное этому

Этот последний код должен быть добавлен внутри события адаптера (не уверен, что событие ведьмы, но в моем случае было onEvent () — com.google.firebase.firestore.EventListener)

Начиная с версии 1.2.0-alpha02 библиотеки androidx recyclerView, она теперь управляется автоматически. Просто добавьте его с помощью:

Перечисление StateRestorationPolicy имеет 3 варианта:

  • РАЗРЕШИТЬ — состояние по умолчанию, которое немедленно восстанавливает состояние RecyclerView на следующем проходе макета
  • PREVENT_WHEN_EMPTY — восстанавливает состояние RecyclerView только тогда, когда адаптер не пустой (adapter.getItemCount () & gt; 0). Если ваши данные загружаются асинхронно, RecyclerView ждет, пока данные будут загружены, и только после этого состояние восстанавливается. Если у вас есть элементы по умолчанию, такие как заголовки или индикаторы выполнения загрузки, как часть вашего адаптера, вам следует использовать параметр PREVENT, если элементы по умолчанию не добавлены с помощью MergeAdapter. MergeAdapter ожидает готовности всех своих адаптеров и только после этого восстанавливает состояние.
  • PREVENT — все восстановление состояния откладывается до тех пор, пока вы не установите ALLOW или PREVENT_WHEN_EMPTY.

Обратите внимание, что на момент этого ответа библиотека recyclerView все еще находится в альфа03, но альфа-фаза не подходит для производственных целей .

Многие из этих ответов, кажется, слишком усложняют его.

LayoutManager поддерживает onRestoreInstanceState из коробки, поэтому нет необходимости сохранять позиции прокрутки и т. Д. Встроенный метод уже сохраняет идеальные позиции пикселей.

Читайте также:  Госуслуги для мобильного андроида

Пример кода фрагмента (нулевая проверка и т. д. удалена для ясности):

Тогда просто позвони

Как только ваши данные будут повторно прикреплены к вашему RecyclerView

Источник

RecyclerView прокрутить до позиции, когда новый элемент добавлен

Я хочу, чтобы мой RecyclerView прокручивал до конца при добавлении нового элемента в список. Ниже мой код:

И когда я нажимаю кнопку, расположенную ниже RecyclerView , данные добавляются в список:

Всякий раз, когда я добавляю элемент, он всегда прокручивается до самой верхней позиции. Я пытался использовать smoothScrollToPosition() и пытался использовать scrollToPosition() на LinearLayoutManager . Я даже пытался использовать ViewTreeObserver . Попытался изменить версию RecyclerView в зависимости тоже. Я тщательно искал Stack Overflow, и ни одно из решений не помогло мне.

Есть идеи, в чем может быть проблема? Я использую RecyclerView внутри фрагмента. Может ли это быть причиной проблемы?

Мой XML-файл для RecyclerView

6 ответов

Если вы хотите добавить данные в конец списка, вам нужно использовать setStackFromEnd() в RecyclerView Layout Manager.

Но сначала вам нужно починить свой адаптер. Вы не должны передавать свой RecylerView вашему адаптеру. Поэтому следующий код неверен:

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

Затем вы можете установить, чтобы данные всегда добавлялись на последнем дне с помощью следующего кода:

Чтобы добавить новые данные, вам лучше сделать новый метод в адаптере. Что-то вроде этого:

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

Помните, что вам нужно переопределить getItemCount() в вашем адаптере. Это должно быть что-то вроде этого:

Пожалуйста, имейте в виду, что в качестве примера я использую Data pojo. Вам нужно изменить его в соответствии с вашим типом данных.

Источник

Как перейти к определенной позиции в recyclerview внутри scrollview?

Я много искал в отношении моего запроса, и ни один из них не был полезен. У меня есть recyclerview и некоторые статические данные внутри прокрутки, которые находятся внутри корневого родительского окна, как показано ниже.

Потому что каждый раз, когда я открываю действие, он переходит к recyclerview firstitem, и он пропускает статические данные выше recyclerview.

Проблема заключается в том,

это не работает. Я установил aboveline после установки адаптера для recyclerview. Также попытался с NestedScrollView, но напрасно.

Хотя я использовал

Для тех, кто пропускает код, я установил match_parent для ScrollView и fillviewport в true.

Необходимо прокрутить ScrollView , получив верхнюю позицию дочернего элемента RecyclerView :

Я знаю, что отвечаю довольно поздно, но если у вас проблема с автопрокруткой, вам нужно добавить android: descendantFocusability = «blocksDescendants» в RelativeLayout. Итак, ваш тег RealtiveLyout будет выглядеть так:

Шаг 1. Добавьте эту строку для выбора этой позиции в recyclerview

Шаг 2: После проверки ниже конструктора, получив текущую позицию

Шаг 3: И эта функция также в адаптере

Последний шаг 4. Добавьте эту функцию вне адаптера в свой класс

Попытайтесь использовать эту строку в элементе списка listview

Эта позиция будет выбрана, когда вы откроете список.

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

Используйте этот метод scrollToPosition (int position), это работает для меня. Надеюсь, что это поможет вам.

Источник

Оцените статью