Начало работы с RecyclerView и CardView на Android
Russian (Pусский) translation by Yuri Yuriev (you can also view the original English article)
Если вам интересно создание приложения для Android, использующего списки для отображения данных, Android Lollipop предлагает два новых виджета, чтобы сделать вашу жизнь проще, RecyclerView
и CardView
. Эти виджеты приведут внешний вид вашего приложения в соответствие с рекомендациями, указанными в спецификации дизайна Google.
Предварительные требования
Для продолжения используйте последнюю версию Android Studio. Можете взять на Android Developer website.
1. Поддержка старых версий
На момент написания статьи менее 2% Android-устройств работали на Android Lollipop. Однако, благодаря v7 Support Library, вы можете использовать виджеты RecyclerView
и CardView
на устройствах более ранних версий Android, добавив следующие строки раздела dependencies в файле build.grade вашего проекта:
compile 'com.android.support:cardview-v7:21.0.+' compile 'com.android.support:recyclerview-v7:21.0.+'
2. Создание CardView
CardView
это ViewGroup
. Как любую ViewGroup
, её можно добавить вActivity
или Fragment
через файл XML.
Чтобы создать пустой CardView
, вам необходимо добавить следующий код в макет XML:
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content"> </android.support.v7.widget.CardView>
Для более реалистичного примера давайте создадим LinearLayout
и поместим в него CardView
. CardView
может представлять, например, человека и содержать следующее:
-
TextView
с именем человека -
TextView
с возрастом человека -
ImageView
с его фотографией
Так будет выглядеть XML:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" > <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/cv" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/person_photo" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginRight="16dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/person_name" android:layout_toRightOf="@+id/person_photo" android:layout_alignParentTop="true" android:textSize="30sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/person_age" android:layout_toRightOf="@+id/person_photo" android:layout_below="@+id/person_name" /> </RelativeLayout> </android.support.v7.widget.CardView> </LinearLayout>
Если этот XML будет макетом Activity
и в полях TextView
и ImageView
значимые показатели, так он будет отображаться на устройстве Android:



3. Создание RecyclerView
Шаг 1. Его определение в макете
С экземпляром RecyclerView
немного сложнее. Однако определить его в макете XML достаточно просто. Вы можете определить его в макете следующим образом:
<android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/rv" />
Чтобы получить к нему доступ в Activity
, возьмите следующий фрагмент:
RecyclerView rv = (RecyclerView)findViewById(R.id.rv);
Если вы уверены, что размер RecyclerView
не изменится, можете добавить следующее для повышения производительности:
rv.setHasFixedSize(true);
Шаг 2. Использование LayoutManager
В отличие от ListView
, RecyclerView
требуется LayoutManager
для управления позициями пунктов. Можете определить свой LayoutManager
путём расширения RecyclerView.LayoutManager
класса. Хотя, можете использовать один из предопределённых подклассов LayoutManager
:
LinearLayoutManager
GridLayoutManager
-
StaggeredGridLayoutManager
В этом уроке я пользуюсь LinearLayoutManager
. LayoutManager
подкласс, по умолчанию, сделает ваш RecyclerView
похожим на ListView
.
LinearLayoutManager llm = new LinearLayoutManager(context); rv.setLayoutManager(llm);
Шаг 3. Определение данных
Подобно ListView
, RecyclerView
нужен адаптер для доступа к своим данным. Но прежде, чем мы создадим адаптер, давайте создадим данные, с которыми будем работать. Создайте простой класс для представления лица, а затем напишите метод инициализации объектов List
of Person
:
class Person { String name; String age; int photoId; Person(String name, String age, int photoId) { this.name = name; this.age = age; this.photoId = photoId; } } private List<Person> persons; // This method creates an ArrayList that has three Person objects // Checkout the project associated with this tutorial on Github if // you want to use the same images. private void initializeData(){ persons = new ArrayList<>(); persons.add(new Person("Emma Wilson", "23 years old", R.drawable.emma)); persons.add(new Person("Lavery Maiss", "25 years old", R.drawable.lavery)); persons.add(new Person("Lillie Watts", "35 years old", R.drawable.lillie)); }
Шаг 4. Создание адаптера
Создавая адаптер для RecyclerView
, надо расширить RecyclerView.Adapter
. Адаптер следует модели view holder , что означает определение пользовательского класса для расширения RecyclerView.ViewHolder
. Эта модель минимизирует количество вызовов метода findViewById
.
Ранее в этом уроке мы уже определили XML для CardView
, который представляет человека. Будем использовать этот макет повторно. Внутри конструктора нашего ViewHolder
инициализируйте представления, относящиеся к элементам нашего RecyclerView
.
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.PersonViewHolder>{ public static class PersonViewHolder extends RecyclerView.ViewHolder { CardView cv; TextView personName; TextView personAge; ImageView personPhoto; PersonViewHolder(View itemView) { super(itemView); cv = (CardView)itemView.findViewById(R.id.cv); personName = (TextView)itemView.findViewById(R.id.person_name); personAge = (TextView)itemView.findViewById(R.id.person_age); personPhoto = (ImageView)itemView.findViewById(R.id.person_photo); } } }
Затем добавьте конструктор в пользовательский адаптер, чтобы он имел доступ к данным, отображаемым RecyclerView
. Поскольку наши данные представлены в виде объектов List
of Person
, используйте следующий код:
List<Person> persons; RVAdapter(List<Person> persons){ this.persons = persons; }
RecyclerView.Adapter
имеет три абстрактных метода, которые мы должны переопределить. Начнём с метода getItemCount
. Это вернёт количество элементов, присутствующих в данных. Поскольку наши данные в List
, назначаем метод size
на объект List
:
@Override public int getItemCount() { return persons.size(); }
Затем переопределите метод onCreateViewHolder
. Как следует из названия, этот метод вызывается для инициализации пользовательского ViewHolder
. Мы указываем макет, который должен использовать каждый элемент RecyclerView
. Это выполняется путем раздувания компоновки с помощью LayoutInflater
, передавая результат конструктору ViewHolde
r.
@Override public PersonViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false); PersonViewHolder pvh = new PersonViewHolder(v); return pvh; }
Переопределите onBindViewHolder
, чтобы указать содержимое каждого элемента RecyclerView
. Этот метод похож на метод getView
адаптера ListView
'. В нашем примере, здесь вы должны установить значения имени, возраста и фотографии в CardView
.
@Override public void onBindViewHolder(PersonViewHolder personViewHolder, int i) { personViewHolder.personName.setText(persons.get(i).name); personViewHolder.personAge.setText(persons.get(i).age); personViewHolder.personPhoto.setImageResource(persons.get(i).photoId); }
Наконец, переопределим onAttachedToRecyclerView
метод. Сейчас мы можем использовать реализацию этого метода в суперклассе, как показано ниже.
@Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); }
Шаг 5. Использование адаптера
Теперь, когда адаптер готов, добавьте следующий код в Activity
, чтобы инициализировать и использовать адаптер, вызывая конструктор адаптера и метод setAdapter
в RecyclerView
:
RVAdapter adapter = new RVAdapter(persons); rv.setAdapter(adapter);
Шаг 6. Сборка и запуск
При запуске примера RecyclerView
на устройстве Android вы увидите нечто похожее.



Заключение
Из урока вы узнали, как использовать виджеты CardView
и RecyclerView
, которые были представлены в Android Lollipop. Вы увидели примеры того, как ими пользоваться в приложениях Material Design. Несмотря на то, что RecyclerView
может делать почти всё, что может ListView
, для небольших наборов данных ListView
по-прежнему предпочтительнее, так как требует меньше строк кода.
Для получения дополнительной информации о классах CardView
и RecyclerView
обратитесь к Android Developers Reference .