В Android, начиная с версии 5.0 Lolipop, доступны новые View-элементы экрана, которые упрощают работу со списками: RecyclerView и CardView. С помощью этих компонентов ваше приложение будет выглядеть и вести себя в соответствии с рекомендациями спецификации Google Material Design.
Предпосылки
Убедитесь, что вы используете последнюю версию Android Studio. Вы можете скачать ее на официальном сайте Android.
1. Поддержка Старых Версий
На момент написания статьи, около 5% Android-устройств работают под управлением Android Lolipop. Однако, наблюдается стремительный рост, а благодаря библиотеке поддержки v7:21, вы можете использовать RecyclerView и CardView на устройства под управлением более старых версий Android.
Для этого добавьте следующие строки в раздел dependencies в файл сборки проекта build.gradle:
1
2
|
compile 'com.android.support:cardview-v7:21.0.+' compile 'com.android.support:recyclerview-v7:21.0.+' |
2. Создание CardView
В CardView является ViewGroup. Как и с любой другой ViewGroup, с CardView можно взаимодействовать в Activity или Fragments, используя XML-файл макета.
Чтобы создать CardView, вам нужно будет добавить следующий код в ваш макет XML, как показано в следующем фрагменте:
1
2
3
4
5
6
|
< android.support.v7.widget.CardView android:layout_width = "match_parent" android:layout_height = "wrap_content" > </ android.support.v7.widget.CardView > |
В нашем конкретном примере нужно создать макет LinearLayout, с CardView внутри. В свою очередь, CardView будет содержать:
- TextView для отображения имени
- TextView для отображения возраста
- ImageView для отображения фото
XML-код макета будет выглядеть так:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
<? xml version = "1.0" encoding = "utf-8" ?> 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 > |
Вот так наполненный данными макет будет выглядеть на экране:
3. Создание RecyclerView
Шаг 1: Определение RecyclerView в Layout
Определяем RecyclerView в макете следующим образом:
1
2
3
4
5
|
< android.support.v7.widget.RecyclerView android:layout_width = "match_parent" android:layout_height = "match_parent" android:id = "@+id/rv" /> |
Для получения ссылки на него в вашей activity, используйте следующий фрагмент кода:
1
|
RecyclerView rv = (RecyclerView)findViewById(R.id.rv); |
Если вы уверены, что размер RecyclerView не будет изменяться, вы можете добавить этот код для улучшения производительности:
1
|
rv.setHasFixedSize( true ); |
Шаг 2: используйте LayoutManager
В отличие от ListView, RecyclerView необходим менеджер компоновки для управления позиционированием своих элементов. Можно определить свой собственный LayoutManager , расширяя класс RecyclerView.LayoutManager. Однако в большинстве случаев, вы могли бы просто использовать один из стандартных подклассов LayoutManager :
LinearLayoutManager
GridLayoutManager
StaggeredGridLayoutManager
В этом уроке я буду использовать LinearLayoutManager. По умолчанию он обеспечивает вид RecyclerView аналогично ListView.
1
2
|
LinearLayoutManager llm = new LinearLayoutManager(context); rv.setLayoutManager(llm); |
Шаг 3: определение данных
Аналогично ListView, в RecyclerView нужен адаптер для доступа к его данным. Но прежде чем мы создадим адаптер, давайте создадим данные, доступные для работы. Напишем простой класс Person, представляющий человека и создадим метод для инициализации списка:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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. Этот адаптер представляет шаблон проектирования viewholder, подразумевающий использование пользовательского класса, который расширяет RecyclerView.ViewHolder. Эта паттерн сводит к минимуму количество обращений к дорогостоящему в плане ресурсов методу findViewById.
Ранее в этом уроке, мы уже определили XML-файл макета для CardView, представляющего человека. Мы собираемся использовать этот макет сейчас. Внутри конструктора нашего кастомного ViewHolder, инициализируем View, входящие в RecyclerView.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
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. Так как наши данные в виде списка объектов Person, используйте следующий код:
1
2
3
4
5
|
List<Person> persons; RVAdapter(List<Person> persons){ this .persons = persons; } |
RecyclerView.Adapter имеет три абстрактных метода, которые мы должны переопределить. Давайте начнем с метода getItemCount. Он вернет количество элементов, присутствующих в данных. Так как наши данные в виде списка, мы просто вызваем метод size к объекту списка:
1
2
3
4
|
@Override public int getItemCount() { return persons.size(); } |
Далее, следует переопределить метод onCreateViewHolder. Как следует из названия, этот метод вызывается, когда кастомный ViewHolder должен быть инициализирован. Мы указываем макет для каждого элемента RecyclerView. Затем LayoutInflater заполняет макет, и передает его в конструктор ViewHolder.
1
2
3
4
5
6
|
@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.
1
2
3
4
5
6
|
@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. В нашем случае мы просто используем суперкласс этого метода, как показано ниже.
1
2
3
4
|
@Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super .onAttachedToRecyclerView(recyclerView); } |
Шаг 5: используем адаптер
Теперь, когда адаптер готов, добавьте следующий код в вашу activity, чтобы инициализировать и использовать адаптер, вызывая в конструктор адаптера и отдавая его методу setAdapter нашего RecyclerView:
1
2
|
RVAdapter adapter = new RVAdapter(persons); rv.setAdapter(adapter); |
Шаг 6: компилируем и запускаем
При запуске нашего примера с CardView и RecyclerView на устройстве Android, вы должны увидеть нечто подобное:
Вывод
В этом уроке мы узнали, как использовать CardView и RecyclerView, которые были введены в Android Lolipop. Вы также видели примеры того, как использовать их в соответствии со спрецификацией Material Design. Заметьте, что хотя RecyclerView может делать почти все, что может и ListView, для небольших наборов данных использовать ListView все же предпочтительнее так как требует меньшего количества строк кода.
Вы можете найти на официальном сайте более подробную информацию о CardView и RecyclerView классах.
Перевод источника. Автор Ashraff Hathibelagal. Скачать исходный код приложения.
1. Для чего используется LinearLayout в recyclerview_activity.xml ? Ведь RecyclerView это контейнер. Без LinearLayout все работает.
2. Для чего используется LinearLayout и RelativeLayout в cardview_activity.xml ? Аналогично весь них все работает.
3. Как установить фон для CardView? android:background не работает.
подскажите, как переделать код, чтобы данные:
persons.add(new Person(«Emma Wilson», «23 years old», R.drawable.emma));
брать с ресурсов String для дальнейшей локализации.
Создайте строковые константы
Ничего не понятно, не могли бы вы указать более подробно, куда именно вписывать фрагменты кода. Где создавать класс person? Попробуйте в пустом макете именно этот код вставить, я думаю у вас не сработает.
Скачайте исходный код по ссылке в конце статьи и увидите структуру, классы и все остальное
Не было бы лишним обновить статью