Может ли RecyclerView создавать более одного "представления" для каждого элемента?
TLDR:
Обычно в RecyclerView
реализация, между Adapter
и LayoutManager
, существует соотношение один просмотр на элемент. Мы надеемся найти способ создать несколько представлений для каждого элемента.
Примечание. Пожалуйста, не путайте это с возможностью создавать различные типы представлений в зависимости от положения адаптера. Для простоты предположим, что существует только один тип просмотра.
Полный вопрос:
Для нашего проекта нам нужно создать список из нескольких столбцов. Список из нескольких столбцов визуально идентичен сетке, но имеет одно заметное отличие; в сетке (как это создано с GridLayoutAdapter
), одна "клетка" (т.е. View
/ ViewHolder
) представляет один элемент. В списке из нескольких столбцов одна строка представляет один элемент. Ячейки, составляющие эту строку, отображают разные свойства одного и того же элемента.
Например, скажем, у меня есть список из десяти объектов Foo, и Foo определяет пять свойств, которые мы хотим отобразить в столбцах. С точки зрения нашего набора данных, есть десять пунктов. С точки зрения LayoutManager
однако существует пятьдесят (десять элементов (строк) умноженных на пять ячеек (столбцов) на строку / элемент.)
Подход, к которому я склоняюсь, заключается в создании RecyclerView.Adapter
/ RecyclerView.LayoutManager
пара.
Во-первых, в моем подклассе адаптера, в дополнение к созданию свойства для хранения моих элементов данных, я также добавил свойство columnCount. Тогда в getItemCount()
переопределить, вместо того, чтобы возвращать количество элементов, как обычно, я возвращаю количество элементов, умноженное на columnCount, вот так:
private List<Object> items;
public List<Object> getItems(){
return items;
}
public void setItems(List<Object> items){
this.items = items;
notifyDataSetChanged();
}
private int columnCount = 1;
public int getColumnCount(){
return columnCount;
}
public void setColumnCount(int columnCount){
this.columnCount = Math.max(columnCount, 1);
notifyDataSetChanged();
}
@Override public final int getItemCount(){
return getItems().size() * getColumnCount();
}
Далее по моему RecyclerView.LayoutManager
В подклассе я настраиваю его для захвата переданного адаптера, и если я могу привести его к конкретному типу адаптера, то я могу получить количество столбцов и использовать его для расчетов макета. Если это не тот тип адаптера, я просто отношусь к нему как к единственному столбцу.
Теперь, когда этот подход работает, он немного запутывает API getItemCount()
больше не возвращает количество реальных элементов, а скорее количество просмотров, что может сбить пользователя с толку. (Я бы хотел, чтобы они назвали это getViewCount()
вместо этого.) Это также означает, что LayoutManager работает только с определенным типом адаптера.
Я также рассмотрел вопрос о том, чтобы сделать его похожим на несколько столбцов, используя горизонтальный LinearLayout для представления всей строки, затем используя его в обычном списке, но это ограничивало нашу гибкость (т.е. мы не можем делать фиксированные строки / столбцы и т. Д.), Поэтому мы оставил это.
Мне интересно, если я подхожу к этому неправильно и / или есть ли API, который я уже могу использовать для этого. Есть ли такая вещь, или я на правильном подходе?
2 ответа
Вы можете достичь этого на уровне адаптера. Вам придется использовать эти три метода.
getItemViewType()
onCreateViewHolder()
onBindViewHolder()
Вот рабочий пример для вашей помощи. Дайте мне знать, если что-то не имеет смысла. Просто сделайте ваш элемент пейджером и добавьте несколько страниц элементов.
https://guides.codepath.com/android/Heterogenous-Layouts-inside-RecyclerView
У вас может быть несколько держателей видов с разными видами, поэтому в зависимости от типа вы можете использовать разные виды.