Как отобразить 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 ответа

Решение

Я помню, когда я впервые читал о RecyclerViews - я согласен, что это может сначала немного запутать. Надеюсь, это объяснение поможет вам лучше понять его.


Основы 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);

        }
    }
}
Другие вопросы по тегам