Как отобразить ArrayList в RecyclerView?
Мне нужно добавить Activity
где я могу перечислить элементы ArrayList<CustomClass>
и я видел, что есть более новый и лучший способ отображения списков - RecyclerView
,
Мой вопрос заключается в том, как реализовать это в моем приложении. Я обнаружил, что мне нужно использовать Adapter
, но я не совсем понимаю, как правильно реализовать весь процесс.
Если вам интересно, я имею в виду примеры документов, которые я читал.
РЕДАКТИРОВАТЬ:
После обновления моего кода он говорит, что не может разрешить символ setOnEntryClickListener
:
public class voting extends Activity {
RecyclerView myList;
private ArrayList<Player> players; // Players
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_voting);
Intent intent = this.getIntent();
Bundle bundle = intent.getExtras();
players = (ArrayList<Player>)bundle.getSerializable("PLAYERS");
myList = (RecyclerView) findViewById(R.id.charactersList);
myList.setLayoutManager(new LinearLayoutManager(this));
CoursesAdapter adapter = new CoursesAdapter(players);
myList.setAdapter(adapter);
}
// OR RecyclerView with a click listener
CoursesAdapter clickAdapter = new CoursesAdapter(players);
clickAdapter.setOnEntryClickListener(new CoursesAdapter.OnEntryClickListener() {
@Override
public void onEntryClick(View view, int position) {
// stuff that will happen when a list item is clicked
}
});
recyclerView.setAdapter(clickAdapter);
}
Так что я думал, что поставил это interface
в неправильном месте (очень вероятно), на самом деле, я поместил его в класс Adapter, в конце, сразу после onAttachedToRecyclerView()
Метод:
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
private OnEntryClickListener mOnEntryClickListener;
public interface OnEntryClickListener {
void onEntryClick(View view, int position);
}
public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
mOnEntryClickListener = onEntryClickListener;
}
}
2 ответа
Я помню, когда я впервые читал о RecyclerView
s - я согласен, что это может сначала немного запутать. Надеюсь, это объяснение поможет вам лучше понять его.
Основы RecyclerView
1. Добавление RecyclerView
Сначала вам нужно добавить свой RecyclerView
к вашему XML-макету. Я предполагаю, что вы знаете, как это сделать. Вы также объявляете это в своем коде Java:
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.your_recycler_view);
2. Создание Adapter
и понимание ViewHolder
Далее вам нужно создать Adapter
для этого. Это класс, который реализуетRecyclerView.Adapter<YourAdapter.YourViewHolder>
, Я объясню, что это значит через минуту.
Я считаю, что это помогает взглянуть на примерAdapter
чтобы понять, как это работает (например, тот, который я создал для приложения с открытым исходным кодом). Я также очень рекомендую просмотреть набор файлов 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
, за исключением того, что вы используете созданный вами метод установки, чтобы управлять тем, что вы будете делать, когда пользователь щелкает конкретный элемент списка.
Чтобы повторить, вы можете просмотреть ряд примеров, которые я сделал на этом Gist на GitHub:
https://gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07
Вот рабочий пример, надеюсь, он вам поможет:
public class BankListAdapter extends RecyclerView.Adapter<BankListAdapter.BankListViewHolder> {
ArrayList<BankListModel> bankListModels;
FragmentActivity activity;
View selectBank;
public BankListAdapter(ArrayList<BankListModel> bankListModels, FragmentActivity activity) {
this.bankListModels=bankListModels;
this.activity=activity;
}
@Override
public BankListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View bankListLayout = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_bank_list, null);
BankListViewHolder bankListViewHolder = new BankListViewHolder(bankListLayout);
return bankListViewHolder;
}
@Override
public void onBindViewHolder(BankListViewHolder holder, int position) {
holder.bankName.setText(bankListModels.get(position).getBankName());
}
@Override
public int getItemCount() {
return bankListModels.size();
}
public class BankListViewHolder extends RecyclerView.ViewHolder {
TextView bankName;
public BankListViewHolder(View itemView) {
super(itemView);
bankName = (TextView) itemView.findViewById(R.id.tv_bankName);
selectBank = itemView.findViewById(R.id.cv_selectBank);
}
}
}