С https://developer.android.com/preview/material/ui-widgets.html
Когда мы создаем, RecyclerView.Adapter
мы должны указать, ViewHolder
что будет связываться с адаптером.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private String[] mDataset;
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ViewHolder(TextView v) {
super(v);
mTextView = v;
}
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.some_layout, parent, false);
//findViewById...
ViewHolder vh = new ViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTextView.setText(mDataset[position]);
}
@Override
public int getItemCount() {
return mDataset.length;
}
}
Итак, возможно ли создать RecyclerView
несколько типов представлений?
Ответы:
Да, это возможно. Просто реализуйте getItemViewType () и позаботьтесь о
viewType
параметре вonCreateViewHolder()
.Итак, вы делаете что-то вроде:
источник
optionMenuItem
. Как это возможно? @AntonSavinЕсли макетов для типов представлений всего несколько, а логика связывания проста, следуйте решению Антона.
Но код будет запутанным, если вам нужно управлять сложными компоновками и логикой связывания.
Я считаю, что следующее решение будет полезно для тех, кому необходимо обрабатывать сложные типы представлений.
Базовый класс DataBinder
Функции, которые необходимо определить в этом классе, во многом идентичны классу адаптера при создании одного типа представления.
Для каждого типа представления создайте класс, расширяя этот DataBinder.
Пример класса DataBinder
Для управления классами DataBinder создайте класс адаптера.
Базовый класс DataBindAdapter
Создайте класс, расширив этот базовый класс, а затем создайте экземпляры классов DataBinder и переопределите абстрактные методы.
getItemCount
Возвращает общее количество элементов DataBinders
getItemViewType
Определите логику отображения между позицией адаптера и типом представления.
getDataBinder
Возвращает экземпляр DataBinder на основе типа представления
getPosition
Определение логики преобразования в позицию адаптера из позиции в указанном DataBinder
getBinderPosition
Определите логику преобразования в позицию в DataBinder из позиции адаптера
Надеюсь, что это решение будет полезным.
Я оставил более подробное решение и примеры в GitHub, поэтому, если вам нужно, перейдите по следующей ссылке.
https://github.com/yqritc/RecyclerView-MultipleViewTypesAdapter
источник
public class DataBinder<T extends RecyclerView.ViewHolder>
может кто-нибудь сказать мне, что<T someClass>
называется, так что я могу гуглить, если я получу термин. Также, когда я говорюabstract public class DataBinder<T extends RecyclerView.ViewHolder>
, означает ли это, что этот класс имеет типViewHolder
, так что в результате каждый класс, который расширяет этот класс, будет иметь такой типviewHolder
?Ниже не псевдокод, и я проверил его, и он работал для меня.
Я хотел создать представление заголовка в моем окне повторного просмотра, а затем отобразить список изображений под заголовком, по которому пользователь может щелкнуть.
Я использовал несколько переключателей в своем коде, не знаю, является ли это наиболее эффективным способом сделать это, поэтому не стесняйтесь комментировать:
источник
Да, это возможно.
Написать общий видовой держатель:
затем создайте свои видоискатели и сделайте так, чтобы они расширяли GenericViewHolder. Например, этот:
тогда класс RecyclerView.Adapter будет выглядеть так:
источник
Создать другой ViewHolder для другого макета
RecyclerView может иметь любое количество виджетов, которое вы хотите, но для лучшей читаемости давайте посмотрим, как создать один с двумя ViewHolders.
public int getItemViewType(int position)
onCreateViewHolder()
методеonBindViewHolder()
методеВот небольшой фрагмент кода
getItemViewType (int position) является ключом
На мой взгляд, отправной точкой для создания такого рода recyclerView является знание этого метода. Поскольку этот метод необязателен для переопределения, он невидим в классе RecylerView по умолчанию, что, в свою очередь, заставляет многих разработчиков (включая меня) задуматься, с чего начать. Как только вы узнаете, что этот метод существует, создание такого RecyclerView станет легкой прогулкой.
Соответствующие ссылки:
Проверьте проект, где я реализовал это
источник
Да, это возможно. В вашем адаптере getItemViewType Layout, как это ....
для ссылки: https://www.journaldev.com/12372/android-recyclerview-example
источник
следуя решению Антона, придумайте,
ViewHolder
что содержит / обрабатывает / делегирует различные типы макетов. Но не уверен, что замена нового макета сработает, если в представлении повторного использованияViewHolder
не указан тип данных.Так что, в основном,
onCreateViewHolder(ViewGroup parent, int viewType)
вызывается только когда требуется новый макет представления;getItemViewType(int position)
будет призван дляviewType
;onBindViewHolder(ViewHolder holder, int position)
всегда вызывается при повторном использовании представления (вводятся новые данные и пытаются их отобразитьViewHolder
).Поэтому, когда
onBindViewHolder
вызывается, нужно правильно расположить макет и обновитьViewHolder
.Правильный ли способ замены макета вида для этого
ViewHolder
, или какая-то проблема? Ценю любой комментарий!Изменить: ViewHolder имеет член mItemViewType для хранения представления
Редактировать: выглядит как в onBindViewHolder (держатель ViewHolder, позиция int), переданный ViewHolder был выбран (или создан) просмотром getItemViewType (позиция int), чтобы убедиться, что это совпадение, поэтому, возможно, нет необходимости беспокоиться о том, что ViewHolder тип не соответствует типу data [position]. Кто-нибудь знает больше, как подобрано ViewHolder в onBindViewHolder ()?
Редактировать: Похоже, что корзина
ViewHolder
выбрана по типу, поэтому там нет воина.Изменить: http://wiresareobsolete.com/2014/09/building-a-recyclerview-layoutmanager-part-1/ отвечает на этот вопрос.
Это получает переработку
ViewHolder
как:или создайте новый, если не найдете корзину
ViewHolder
правильного типа.источник
У меня есть лучшее решение, которое позволяет создавать несколько типов представлений декларативным и безопасным способом. Это написано на Kotlin, что, кстати, действительно приятно.
Простые держатели видов для всех необходимых типов видов
Существует абстракция элемента данных адаптера. Обратите внимание, что тип представления представлен хэш-кодом определенного класса держателя вида (KClass на Kotlin)
Только
bindViewHolder
нужно быть переопределены в конкретных классов адаптера элементов (типа безопасный способ)Список таких
AdapterItemMedium
объектов является источником данных для адаптера, который фактически принимает,List<AdapterItem>
см. Ниже.Важной частью этого решения является фабрика держателей представлений, которая предоставит свежие экземпляры определенного ViewHolder
И простой класс адаптера выглядит следующим образом
Всего 3 шага для создания нового вида:
ViewHolderProvider
Вот пример этой концепции: Android-ящик-шаблон Это идет еще дальше - просмотр типа, который действует как компонент счетчика, выбираемые элементы адаптера.
источник
Это очень просто и прямо.
Просто переопределите метод getItemViewType () в вашем адаптере. На основании данных возвращают разные значения itemViewType. Например, рассмотрим объект типа Person с членом isMale, если isMale равен true, вернуть 1, а isMale - false, вернуть 2 в методе getItemViewType () .
Теперь приходит к createViewHolder (родительский ViewGroup, int viewType) , на основе различных viewType вы можете раздувать другой файл макета. как следующее
в onBindViewHolder (VH holder, int position) проверьте, где holder является экземпляром
AdapterFemaleViewHolder
илиAdapterMaleViewHolder
by,instanceof
и, соответственно, присвойте значения.ViewHolder Может быть так
источник
Хотя выбранный ответ является правильным, я просто хочу уточнить его. Я нашел здесь полезный пользовательский адаптер для нескольких типов представлений в RecyclerView . Его версия Kotlin здесь .
Пользовательский адаптер следующий
источник
Я рекомендую эту библиотеку от Ханнеса Дорфмана. Он инкапсулирует всю логику, связанную с конкретным типом представления, в отдельный объект с именем «AdapterDelegate». https://github.com/sockeqwe/AdapterDelegates
источник
На самом деле, я хотел бы улучшить ответ Антона .
Поскольку
getItemViewType(int position)
возвращает целочисленное значение, вы можете вернуть идентификатор ресурса макета, который вам нужно будет раздувать. Таким образом, вы сохраните некоторую логику вonCreateViewHolder(ViewGroup parent, int viewType)
методе.Кроме того, я бы не советовал проводить интенсивные вычисления,
getItemCount()
поскольку эта конкретная функция вызывается как минимум 5 раз при визуализации списка, а также при визуализации каждого элемента за пределами видимых элементов. К сожалению, посколькуnotifyDatasetChanged()
метод является окончательным, вы не можете переопределить его, но вы можете вызвать его из другой функции в адаптере.источник
Note: Integers must be in the range 0 to getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPE can also be returned.
Так что лучше писать немного больше кода и не использовать хаки.Вы можете использовать библиотеку: https://github.com/vivchar/RendererRecyclerViewAdapter
`
Для каждого элемента вы должны реализовать ViewRenderer, ViewHolder, SomeModel:
ViewHolder - это простой видовой держатель вида рециркулятора.
SomeModel - это ваша модель с
ItemModel
интерфейсомДля более подробной информации вы можете посмотреть документацию.
источник
Реализация типов представлений становится проще с kotlin, вот пример с этой легкой библиотекой https://github.com/Link184/KidAdapter
источник
Вы можете иметь дело с множеством
RecyclerAdapter
ViewTypes,getItemViewType()
возвращая ожидаемоеviewType
значение для этой позицииЯ подготовил
MultipleViewTypeAdapter
для составления списка MCQ для экзаменов, в котором может быть задан вопрос, который может иметь 2 или более действительных ответов (варианты флажков) и вопросы с одним ответом (параметры радиопереключателей).Для этого я получил тип Вопроса из ответа API и использовал его для решения, какое представление мне нужно показать для этого вопроса.
Вы можете избежать нескольких условных заполнений данных viewHolder
onBindViewHolder()
, назначая одинаковые идентификаторы для одинаковых представлений в viewHolder, которые различаются по своему расположению.источник
Если вы хотите использовать его в сочетании с привязкой данных Android, загляните в https://github.com/evant/binding-collection-adapter - это, безусловно, лучшее решение для нескольких типов представлений, которые
RecyclerView
я когда-либо видел.вы можете использовать его как
а затем в макете, где список
Ваши элементы списка должны реализовывать
BaseListItem
интерфейс, который выглядит следующим образоми элемент должен выглядеть примерно так
Где
YourListItem
реализуетBaseListItem
Надеюсь, это кому-нибудь поможет.
источник
Сначала вы должны создать 2 макета XML. после этого в адаптере просмотра переработчика TYPE_CALL и TYPE_EMAIL находятся два статических значения с 1 и 2 соответственно в классе адаптера.
Теперь определим два статических значения на уровне класса адаптера представления Recycler, например: private static int TYPE_CALL = 1; private static int TYPE_EMAIL = 2;
Теперь создайте видовой держатель с несколькими видами, как это:
Теперь код, как показано ниже, в методах onCreateViewHolder и onBindViewHolder в адаптере recyclerview:
источник