- Как сохранить позицию прокрутки RecyclerView с помощью RecyclerView.State?
- Обновить
- Старый ответ
- Простой пример Android RecyclerView
- Обновить зависимости Gradle
- Создать макет занятия
- Создать макет строки
- Создайте адаптер
- Инициализировать RecyclerView в действии
- Законченный
- Продолжается
- дальнейшее чтение
- Минимальное представление Recycler, готовое к использованию шаблона Kotlin для:
- Это будет самый простой вариант реализации RecyclerView.
- activity_main.xml
- list_item_view.xml
- CustomAdapter.java
- MainActivity.java
- Теперь вам нужен 1 адаптер на все RecyclerView
- Вы не хотите слишком много читать, напрямую клонируйте / загружайте полный пример из моего репозитория github. И попробуйте сами.
Как сохранить позицию прокрутки RecyclerView с помощью RecyclerView.State?
У меня вопрос об Android RecyclerView.State .
Я использую RecyclerView, как я могу использовать и связать его с RecyclerView.State?
Моя цель — сохранить позицию прокрутки RecyclerView .
Как вы планируете сохранять последнюю сохраненную позицию с помощью RecyclerView.State ?
Вы всегда можете рассчитывать на хорошее состояние сохранения. Расширить RecyclerView и переопределить onSaveInstanceState () и onRestoreInstanceState() :
Обновить
Введено начиная с recyclerview:1.2.0-alpha02 релиза StateRestorationPolicy . Это мог бы быть лучший подход к данной проблеме.
Кроме того, @ rubén-viguera поделился более подробной информацией в ответе ниже. https://stackoverflow.com/a/61609823/892500
Старый ответ
Если вы используете LinearLayoutManager, он поставляется с предварительно созданным api сохранения linearLayoutManagerInstance.onSaveInstanceState () и восстановлением api linearLayoutManagerInstance.onRestoreInstanceState (. )
При этом вы можете сохранить возвращенную посылку в своем другом штате. например,
, и восстановить положение с сохраненным состоянием. например,
Подводя итог, ваш окончательный код будет выглядеть примерно так:
Изменить: вы также можете использовать тот же API с GridLayoutManager, так как это подкласс LinearLayoutManager. Спасибо @wegsehen за предложение.
Изменить: помните, что если вы также загружаете данные в фоновом потоке, вам понадобится вызов onRestoreInstanceState в вашем методе onPostExecute / onLoadFinished для восстановления позиции при изменении ориентации, например
и если это не сработает, попробуйте
Положить в магазин onPause() и восстановить в onResume()
Я хотел сохранить позицию прокрутки Recycler View, когда уходил от своей активности в списке, а затем нажимал кнопку «Назад», чтобы вернуться назад. Многие решения этой проблемы были либо намного сложнее, чем требовалось, либо не работали для моей конфигурации, поэтому я решил поделиться своим решением.
Сначала сохраните состояние вашего экземпляра в onPause, как многие показали. Думаю, здесь стоит подчеркнуть, что эта версия onSaveInstanceState является методом из класса RecyclerView.LayoutManager.
Ключ к правильной работе — это убедиться, что вы вызываете onRestoreInstanceState после присоединения адаптера, как некоторые указывали в других потоках. Однако фактический вызов метода намного проще, чем многие указывали.
Я устанавливаю переменные в onCreate (), сохраняю позицию прокрутки в onPause () и устанавливаю позицию прокрутки в onResume ()
Вам больше не нужно сохранять и восстанавливать состояние самостоятельно. Если вы установите уникальный идентификатор в xml и recyclerView.setSaveEnabled (true) (true по умолчанию), система автоматически сделает это. Подробнее об этом: http://trickyandroid.com/saving-android-view-state-correctly/
Все менеджеры компоновки, входящие в состав библиотеки поддержки, уже знают, как сохранять и восстанавливать положение прокрутки.
Положение прокрутки восстанавливается при первом проходе макета, что происходит при соблюдении следующих условий:
- менеджер по расположению прикреплен к RecyclerView
- адаптер прилагается к RecyclerView
Обычно вы устанавливаете диспетчер компоновки в XML, поэтому все, что вам нужно сделать сейчас, это
- Загрузите адаптер с данными
- Затем прикрепите адаптер к RecyclerView
Вы можете сделать это в любое время, это не ограничено Fragment.onCreateView или Activity.onCreate .
Пример: убедитесь, что адаптер подключен каждый раз при обновлении данных.
Сохраненная позиция прокрутки рассчитывается на основе следующих данных:
- Положение адаптера первого элемента на экране
- Пиксельное смещение верха элемента от верха списка (для вертикального расположения)
Поэтому вы можете ожидать небольшого несоответствия, например, если ваши элементы имеют разные размеры в портретной и альбомной ориентации.
RecyclerView / ScrollView / Что нужно иметь android:id для своего государства , чтобы спастись.
Вот мой подход к их сохранению и поддержанию состояния recyclerview во фрагменте. Сначала добавьте изменения конфигурации в родительскую активность, как показано ниже.
Затем в своем фрагменте объявите этот метод экземпляра
Добавьте ниже код в свой метод @onPause
Добавьте метод onConfigartionChanged, как показано ниже.
Этот подход решит вашу проблему. если у вас другой менеджер компоновки, просто замените верхний менеджер компоновки.
Вот как я восстанавливаю позицию RecyclerView с помощью GridLayoutManager после вращения, когда вам нужно перезагрузить данные из Интернета с помощью AsyncTaskLoader.
Сделайте глобальную переменную Parcelable и GridLayoutManager и статическую финальную строку:
Сохранение состояния gridLayoutManager в onSaveInstance ()
Восстановить в onRestoreInstanceState
Затем, когда загрузчик извлекает данные из Интернета, вы восстанавливаете позицию recyclerview в onLoadFinished ()
.. конечно, вам нужно создать экземпляр gridLayoutManager внутри onCreate. Ура
У меня было такое же требование, но решения здесь не совсем помогли мне перейти линию из-за источника данных для recyclerView.
Я извлекал состояние LinearLayoutManager RecyclerViews в onPause ()
Parcelable state сохраняется onSaveInstanceState(Bundle outState) и снова извлекается onCreate(Bundle savedInstanceState) , когда savedInstanceState != null .
Однако адаптер recyclerView заполняется и обновляется объектом ViewModel LiveData, возвращаемым вызовом DAO в базу данных Room.
В конце концов я обнаружил, что восстановление состояния экземпляра непосредственно после установки данных в адаптере будет сохранять состояние прокрутки при поворотах.
Я подозреваю, что это связано либо с тем, что LinearLayoutManager состояние, которое я восстановил, было перезаписано, когда данные были возвращены вызовом базы данных, либо восстановленное состояние было бессмысленным для «пустого» LinearLayoutManager.
Если данные адаптера доступны напрямую (т. Е. Не связаны с вызовом базы данных), то восстановление состояния экземпляра в LinearLayoutManager может быть выполнено после того, как адаптер установлен в recyclerView.
Различие между двумя сценариями удерживало меня целую вечность.
На уровне 28 Android API я просто проверяю, что настроил свой метод LinearLayoutManager and RecyclerView.Adapter in my Fragment#onCreateView , и все работает Just Worked ™ ️. Мне не нужно было ничего делать onSaveInstanceState или onRestoreInstanceState работать.
Ответ Евгения Печанека объясняет, почему это работает.
Начиная с версии 1.2.0-alpha02 библиотеки androidx recyclerView, она теперь управляется автоматически. Просто добавьте его с помощью:
Перечисление StateRestorationPolicy имеет 3 варианта:
- РАЗРЕШИТЬ — состояние по умолчанию, которое восстанавливает состояние RecyclerView немедленно, на следующем проходе макета
- PREVENT_WHEN_EMPTY — восстанавливает состояние RecyclerView только тогда, когда адаптер не пустой (adapter.getItemCount ()> 0). Если ваши данные загружаются асинхронно, RecyclerView ждет, пока данные будут загружены, и только после этого состояние восстанавливается. Если у вас есть элементы по умолчанию, такие как заголовки или индикаторы выполнения загрузки, как часть вашего адаптера, вы должны использовать опцию PREVENT, если только элементы по умолчанию не добавлены с помощью MergeAdapter . MergeAdapter ожидает готовности всех своих адаптеров и только после этого восстанавливает состояние.
- PREVENT — все восстановление состояния откладывается до тех пор, пока вы не установите ALLOW или PREVENT_WHEN_EMPTY.
Обратите внимание, что на момент этого ответа библиотека recyclerView все еще находится в alpha03, но альфа-фаза не подходит для производственных целей .
Для меня проблема заключалась в том, что я каждый раз настраивал новый менеджер компоновки при смене адаптера, теряя позицию прокрутки очереди в recyclerView.
Я просто хотел бы поделиться недавней проблемой, с которой я столкнулся с RecyclerView. Я надеюсь, что любой, кто сталкивается с такой же проблемой, выиграет.
Требования к моему проекту: Итак, у меня есть RecyclerView, в котором перечислены некоторые интерактивные элементы в моем основном действии (Activity-A). При щелчке по элементу отображается новое действие с подробностями об элементе (действие-B).
Я реализовал в файле манифеста то, что Activity-A является родительским для Activity-B, таким образом, у меня есть кнопка возврата или возврата на панель действий Activity-B.
Проблема: каждый раз, когда я нажимал кнопку «Назад» или «Домой» на панели действий Activity-B, Activity-A переходит в полный жизненный цикл действия, начиная с onCreate ().
Несмотря на то, что я реализовал onSaveInstanceState (), сохраняющий список адаптера RecyclerView, когда Activity-A запускает его жизненный цикл, saveInstanceState всегда имеет значение null в методе onCreate ().
Продолжая копаться в Интернете, я столкнулся с той же проблемой, но человек заметил, что кнопка «Назад» или «Домой» под устройством Anroid (кнопка «Назад / Домой по умолчанию») Activity-A не входит в жизненный цикл активности.
- Я удалил тег для родительской активности в манифесте для Activity-B
Я включил кнопку «Домой» или «Назад» на Activity-B
В методе onCreate () добавьте эту строку supportActionBar? .SetDisplayHomeAsUpEnabled (true)
В методе overide fun onOptionsItemSelected () я проверил item.ItemId, по которому щелкают элемент, на основе идентификатора. Идентификатор кнопки возврата:
android.R.id.home
Затем реализуйте вызов функции finish () внутри android.R.id.home
Это завершит Activity-B и принесет Acitivy-A без прохождения всего жизненного цикла.
Для моих требований это пока лучшее решение.
Источник
Простой пример Android RecyclerView
Я несколько раз составлял список элементов с помощью Android RecyclerView , но это довольно сложный процесс. Я просматриваю одно из многочисленных онлайн-руководств ( это , это и это хорошо), но я ищу простой пример, который я могу скопировать и вставить, чтобы быстро приступить к работе. Необходимы только следующие функции:
- Вертикальная планировка
- Один TextView в каждой строке
- Реагирует на события щелчка
Поскольку я хотел этого несколько раз, я, наконец, решил дать ответ ниже для моей и вашей будущей ссылки.
Ниже приведен минимальный пример, который будет выглядеть как на следующем изображении.
Начните с пустого занятия. Вы выполните следующие задачи, чтобы добавить RecyclerView. Все, что вам нужно сделать, это скопировать и вставить код в каждый раздел. Позже вы сможете настроить его под свои нужды.
- Добавить зависимости в gradle
- Добавьте файлы макета xml для действия и для строки RecyclerView
- Сделайте адаптер RecyclerView
- Инициализируйте RecyclerView в своей деятельности
Обновить зависимости Gradle
Убедитесь, что в вашем gradle.build файле приложения есть следующие зависимости :
Вы можете обновить номера версий до самых последних . Используйте, compile а не, implementation если вы все еще используете Android Studio 2.x.
Создать макет занятия
Добавьте в RecyclerView свой xml-макет.
Создать макет строки
У каждой строки в нашем RecyclerView будет только один TextView . Создайте новый файл ресурсов макета.
Создайте адаптер
RecyclerView Нужен адаптер для заполнения представлений в каждой строке с данными. Создайте новый файл java.
- Хотя это и не является строго необходимым, я включил функцию прослушивания событий щелчка по строкам. Это было доступно в старом ListViews и является обычной потребностью. Вы можете удалить этот код, если он вам не нужен.
Инициализировать RecyclerView в действии
Добавьте следующий код к своему основному действию.
- Обратите внимание, что действие реализует то, ItemClickListener что мы определили в нашем адаптере. Это позволяет нам обрабатывать события щелчка по строке в onItemClick .
Законченный
Вот и все. Теперь вы сможете запустить свой проект и получить что-то похожее на изображение вверху.
Продолжается
Добавление разделителя между строками
Вы можете добавить такой простой разделитель
Если вы хотите что-то посложнее, см. Следующие ответы:
Изменение цвета строки при нажатии
Посмотрите этот ответ, чтобы узнать, как изменить цвет фона и добавить эффект пульсации при щелчке строки.
Обновление строк
См. Этот ответ, чтобы узнать, как добавлять, удалять и обновлять строки.
дальнейшее чтение
Минимальное представление Recycler, готовое к использованию шаблона Kotlin для:
- Вертикальная планировка
- Один TextView в каждой строке
- Реагирует на события щелчка (одиночное и долгое нажатие)
Я знаю, что это старая ветка, и здесь есть ответы. Добавляем этот ответ для использования в будущем:
Добавьте вид корзины в свой макет
Создайте макет для отображения элементов списка (list_item.xml)
Теперь создайте минимальный адаптер для хранения данных, код здесь не требует пояснений.
Добавьте этот класс для обработки событий одиночного и длительного щелчка по элементам списка
Наконец, установите свой адаптер в режим Recycler View и добавьте Touch Listener, чтобы начать перехват события касания для одиночного или двойного нажатия на элементы списка.
Бонус; Обновить данные
Это будет самый простой вариант реализации RecyclerView.
activity_main.xml
list_item_view.xml
CustomAdapter.java
MainActivity.java
Начните с добавления библиотеки recyclerview.
Создайте класс модели.
создать класс адаптера.
создать макет row_uses.xml
Найдите recyclerview и заполните данные.
найти полное руководство и исходный код здесь:
На основе разных источников я создал простую реализацию RecyclerView с использованием простой библиотеки.
Добавьте эту строку в build.gradle
Добавить Создайте RecyclerView, добавив MyRecyclerView в activity_main.xml с помощью
Теперь в MainActivity создайте ViewHolder, передав имя класса, который необходимо привязать
Создайте переменную списка элементов и адаптеры с очень небольшим количеством строк, передав элементы, класс и макет в адаптер
ClickListener можно добавить следующими строками
Больше примеров и реализации можно найти здесь . Надеюсь это поможет .
Теперь вам нужен 1 адаптер на все RecyclerView
- Один адаптер можно использовать для всех RecyclerView. Так что НЕТ onBindViewHolder , никакой onCreateViewHolder обработки.
- Нет кода для настройки адаптера из класса Java / Kotlin. Проверить образец класса .
- Вы можете установить события и пользовательские данные для каждого списка с помощью адаптеров привязки .
Я показываю здесь установку двух разных RecyclerView по 1 адаптеру —
activity_home.xml
Вы можете увидеть список передач, идентификатор макета элемента и прослушиватель щелчков из макета.
Эти настраиваемые атрибуты создаются BindingAdapter .
Теперь из Activity вы передаете список, нажимаете слушателя, например
HomeActivity.java
Вы не хотите слишком много читать, напрямую клонируйте / загружайте полный пример из моего репозитория github. И попробуйте сами.
Вы можете увидеть GeneralAdapter.java в репо выше.
Если у вас возникли проблемы при настройке привязки данных, см. Этот ответ .
Поскольку я пока не могу комментировать, я опубликую ссылку в качестве ответа. Я нашел простой, хорошо организованный учебник по recyclerview http://www.androiddeft.com/2017/10/01/recyclerview-android/
Кроме того, когда вы собираетесь добавить представление ресайклера в свою деятельность, вы хотите сделать, как показано ниже, и как вы должны это делать, было описано по ссылке
- добавить компонент RecyclerView в файл макета
- создать класс, который вы собираетесь отображать в виде строк списка
- создать файл макета, который является макетом строки вашего списка
- теперь нам нужен специальный адаптер, поэтому создайте собственный адаптер, расширив родительский класс RecyclerView.Adapter
- добавьте recyclerview в свой mainActivity oncreate
- добавление разделителей
- добавление слушателей Touch
Вы можете использовать абстрактный адаптер с утилитами diff и фильтром
SimpleAbstractAdapter.kt
И расширить абстрактный адаптер с помощью методов реализации
ЗадачиAdapter.kt
добавить собственный фильтр
Вот гораздо более новое решение Kotlin для этого, которое намного проще, чем многие из написанных здесь ответов, оно использует анонимный класс.
Я взял на себя смелость использовать android.R.layout.simple_list_item_1, так как это проще. Я хотел еще больше упростить его и поместить ItemHolder в качестве внутреннего класса, но не мог понять, как ссылаться на него в типе во внешнем параметре класса.
реализация androidx.recyclerview: recyclerview: . Рекомендуется обновить библиотеки androidx, которые находятся здесь:
Затем необходимо обновить XML-тег Widget файла макета до: androidx.recyclerview.widget.RecyclerView
Зависимости
Один класс для элемента Click
Второй класс RecyclerView
Класс адаптера для элемента вторичной переработки
Источник