Ответ 1
Помню, когда я впервые прочитал о RecyclerView
- я согласен, что это может быть немного запутанным вначале. Надеюсь, это объяснение поможет вам лучше понять.
Основы RecyclerView
1. Добавление RecyclerView
Сначала вам нужно добавить RecyclerView
в свой XML-макет. Я предполагаю, что вы знаете, как это сделать. Вы также объявляете это в своем Java-коде:
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.your_recycler_view);
2. Создание Adapter
и понимание ViewHolder
Затем вам нужно создать Adapter
. Это класс, который реализует RecyclerView.Adapter<YourAdapter.YourViewHolder>
. Я объясню, что это означает через минуту.
Я считаю, что это помогает взглянуть на пример Adapter
, чтобы понять, как он работает (например, тот, который я создал для open- исходное приложение). Я также настоятельно рекомендую просмотреть набор файлов Java, которые я привел в качестве примера в Gist на GitHub:
https://gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07
Я буду ссылаться на файлы примеров из ссылки выше в этом объяснении, чтобы вы могли следовать.
Вы можете видеть, что класс Adapter
содержит внутренний класс, который является вашим ViewHolder
. Поэтому ему необходимо расширить RecyclerView.ViewHolder
.
Внутри этого ViewHolder
вы объявляете переменные для макетов, которые будут использоваться для каждого элемента списка в RecyclerView
. В конструкторе для вашего ViewHolder
вы назначаете эти переменные. Я имею в виду эту часть кода (я приводил свой пример ниже):
ExampleViewHolder(View itemView) {
super(itemView);
text1 = (TextView) itemView.findViewById(R.id.text1);
text2 = (TextView) itemView.findViewById(R.id.text2);
}
Это все, что вам нужно для вашего ViewHolder
(внутренний класс в вашем Adapter
).
3. Понимание Adapter
Как и большинство объектов Java, вам нужно будет иметь конструктор некоторых частных переменных в вашем классе Adapter
. Вот мои:
private ArrayList<CustomClass> mCustomObjects;
public ExampleAdapter(ArrayList<CustomClass> arrayList) {
mCustomObjects = arrayList;
}
Вам нужно будет указать ArrayList<CustomClass>
как конструктор, чтобы вы могли передать список, чтобы ваш Adapter
мог его использовать.
Если вы посмотрите на остальную часть класса Adapter
, он содержит некоторые методы, которые он переопределяет от того, что он расширяет. Давайте быстро посмотрим, что это такое:
-
getItemCount()
возвращает размер вашего списка. -
onCreateViewHolder(...)
используется для раздувания макета для вашего элемента списка. -
onBindViewHolder(...)
настраивает ваши макеты для элемента списка (например, установка текста вTextView
)
В большинстве случаев getItemCount()
просто вернет size()
вашего ArrayList<CustomClass>
.
Метод onCreateViewHolder(...)
обычно остается таким же:
@Override
public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_2, parent, false);
return new ExampleViewHolder(view);
}
Вы можете видеть, что я раздуваю макет, который я буду использовать в качестве элемента списка (android.R.layout.simple_list_item_2
). Этот макет встроен в Android, поэтому мне не нужно его создавать - конечно, вы можете использовать любой макет, который хотите, а затем изменить свой Adapter
для виджетов, которые вы можете использовать. Тип возврата этого метода будет соответствовать тому, что вы назвали своим внутренним классом ViewHolder
.
Теперь интересный бит находится в onBindViewHolder(...)
. Здесь вы настраиваете свои макеты, поэтому полностью зависит от вас, что вы хотите сделать. Здесь вы можете использовать шаблон:
@Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
CustomClass object = mCustomObjects.get(position);
String firstText = object.getFirstText()
String secondText = object.getSecondText()
holder.text1.setText(firstText);
holder.text2.setText(secondText);
}
В принципе, вы получаете доступ к своим переменным ViewHolder
(для виджетов в макете вашего списка), делая holder.myWidget
. Часть holder
исходит из параметра, который является вашим ViewHolder
, о котором мы говорили ранее, и myWidget
будет именем переменной View
.
В приведенном выше примере object
имеет метод getFirstText()
, а ViewHolder
содержит TextView
(text1
), поэтому я устанавливаю текст.
Существует еще один метод - onAttachedToRecyclerView(...)
. Вы можете использовать это для более сложных вещей, но на базовом уровне обычно это:
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
4. Конфигурирование RecyclerView
Помните в начале, когда мы объявили и назначили наш RecyclerView
?:
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.your_recycler_view);
Теперь мы настроим его.
Вы начинаете с установки "менеджера макетов". Это определяет, как каждый элемент списка будет отображаться на экране. Обычными являются LinearLayoutManager
и GridLayoutManager
. Первый помещает элементы списка в стандартный список (ничего особенного, но очень полезно), а последний упорядочивает элементы списка в виде сетки.
В нашем примере мы будем использовать LinearLayoutManager
. Чтобы установить это на RecyclerView
, мы делаем следующее:
recyclerView.setLayoutManager(new LinearLayoutManager(this));
Что все.
И все, что нам нужно сделать, это установить класс Adapter
, который мы создали и настроили ранее, на RecyclerView
:
ExampleAdapter adapter = new ExampleAdapter(yourCustomArrayList);
recyclerView.setAdapter(adapter);
В приведенном выше примере я предполагаю, что ваш Adapter
имеет только один параметр, но это будет зависеть от того, как вы его настроили ранее.
5. Используя RecyclerView
Вышеупомянутые шаги должны дать вам рабочий RecyclerView
. Если вы застряли, вы можете посмотреть, как я добавил его в свое приложение здесь.
Вы также можете просмотреть образцы Google для реализации RecyclerView
.
Я надеюсь, что все это дало вам четкое представление о том, как работает RecyclerView
.
Добавление прослушивателя кликов
Вам может понадобиться добавить прослушиватель кликов, чтобы вы не использовали RecyclerView
только для отображения элементов.
Для этого вашему внутреннему классу ViewHolder
необходимо реализовать View.OnClickListener
. Это связано с тем, что вы установите OnClickListener
в параметр itemView
конструктора ViewHolder
. Позвольте мне показать вам, что я имею в виду:
public class ExampleClickViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView text1, text2;
ExampleClickViewHolder(View itemView) {
super(itemView);
// we do this because we want to check when an item has been clicked:
itemView.setOnClickListener(this);
// now, like before, we assign our View variables
title = (TextView) itemView.findViewById(R.id.text1);
subtitle = (TextView) itemView.findViewById(R.id.text2);
}
@Override
public void onClick(View v) {
// The user may not set a click listener for list items, in which case our listener
// will be null, so we need to check for this
if (mOnEntryClickListener != null) {
mOnEntryClickListener.onEntryClick(v, getLayoutPosition());
}
}
}
Единственное, что вам нужно добавить, это настраиваемый интерфейс для вашего Adapter
и метода сеттера:
private OnEntryClickListener mOnEntryClickListener;
public interface OnEntryClickListener {
void onEntryClick(View view, int position);
}
public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
mOnEntryClickListener = onEntryClickListener;
}
Итак, ваш новый, поддерживающий клики Adapter
завершен.
Теперь, используйте его...
ExampleClickAdapter clickAdapter = new ExampleClickAdapter(yourObjects);
clickAdapter.setOnEntryClickListener(new ExampleClickAdapter.OnEntryClickListener() {
@Override
public void onEntryClick(View view, int position) {
// stuff that will happen when a list item is clicked
}
});
recyclerView.setAdapter(clickAdapter);
В основном, как вы настроите обычный Adapter
, за исключением того, что вы используете свой метод setter, который вы создали, чтобы контролировать, что вы будете делать, когда пользователь нажимает на определенный элемент списка.
Чтобы повторить, вы можете просмотреть набор примеров, которые я сделал в этом Gist на GitHub:
https://gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07