Статьи

Android Listview с многострочным макетом

Во многих постах мы много говорили о ListView и о том, как с ним обращаться: создавая собственный адаптер или обрабатывая взаимодействия с пользователем.

В этой статье я расскажу о другом аспекте, связанном с ListView, который не был рассмотрен в прошлом: ListView с многострочным макетом. К настоящему времени мы видели строки, имеющие одинаковую разметку, в любом случае возможно иметь строки с разной разметкой.

Мы хотим иметь что-то вроде картинки, показанной ниже:

android_listview_multiple_layout5

В этом приложении мы показываем список контактов, который имеет два разных макета, один из которых использует изображение, а другой — без изображения. Даже если пример довольно прост, достаточно понять, как использовать несколько методов ListView для получения этого результата.

Как сделать несколько макетов

Обычно, когда мы хотим настроить данные ListView мы используем специальный адаптер . Мы знаем, что Android предоставляет готовый к использованию базовый адаптер (например, ArrayAdapter , SimpleAdapter и т. Д.). Мы уже знаем, что все эти адаптеры имеют общий родительский класс, известный как BaseAdapter .

Когда мы хотим настроить способ отображения данных в ListView, мы можем использовать один из классов адаптеров, предоставляемых Android, или реализовать наш специальный адаптер, в этом случае мы создадим специальный адаптер, расширяющий BaseAdapter .

BaseAdapter имеет два метода, которые очень полезны, если мы хотим иметь несколько рядов макетов:

  • public int getItemViewType (int position)
  • public int getViewTypeCount ()

Метод getViewTypeCount «возвращает количество типов представлений, которые будут созданы getView (int, View, ViewGroup) ».

Другими словами, этот метод возвращает, сколько разных макетов у нас в ListView. getItemViewType возвращает тип представления текущей строки, если вы посмотрите на сигнатуру метода, у нас есть позиция в качестве параметра. Следует отметить, что этот метод должен возвращать целочисленное значение между 0 и getViewTypeCount () — 1.

Поэтому, если мы хотим иметь многострочный макет, мы должны переопределить эти методы и вернуть правильные значения.

Реализация многострочного макета

Прежде всего, мы должны создать собственный адаптер, который мы называем ContactAdapter :

1
2
3
public class ContactAdapter extends BaseAdapter {
...
}

и чтобы иметь два разных макета, мы переопределяем:

1
2
3
4
@Override
public int getViewTypeCount() {
    return 2;
}

и затем мы должны реализовать логику, чтобы выбрать тип макета для назначения в соответствии со значением позиции:

1
2
3
4
@Override
public int getItemViewType(int position) {
    return (contactList.get(position).getContactType() == ContactType.CONTACT_WITH_IMAGE) ? 0 : 1;
}

В этом методе мы используем getContactType чтобы узнать, какой макет использовать, как вы видите, мы возвращаем 0 или 1.

Теперь нам нужно реализовать два разных макета: они очень похожи:

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
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="wrap_content">
 
    <ImageView
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:id="@+id/img"/>
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/name"
        android:layout_toRightOf="@id/img"
        android:layout_marginTop="2dp"/>
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/surname"
        android:layout_toRightOf="@id/name"
        android:layout_marginLeft="4dp"/>
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/email"
        android:layout_below="@id/name"
        android:layout_alignStart="@id/name"
        android:layout_marginTop="4dp"/>
</RelativeLayout>

а другой без изображения:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="wrap_content">
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/name"/>
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/surname"
        android:layout_toRightOf="@id/name"
        android:layout_marginLeft="4dp"/>
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/email"
        android:layout_below="@id/name"
        android:layout_alignStart="@id/name"
        android:layout_marginTop="4dp"/>
</RelativeLayout>

Теперь нам нужно просто переопределить в нашем пользовательском адаптере метод getView :

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
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    int type = getItemViewType(position);
    if (v == null) {
        // Inflate the layout according to the view type
        LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (type == 0) {
            // Inflate the layout with image
            v = inflater.inflate(R.layout.image_contact_layout, parent, false);
        }
        else {
            v = inflater.inflate(R.layout.simple_contact_layout, parent, false);
        }
    }
    //
    Contact c = contactList.get(position);
 
    TextView surname = (TextView) v.findViewById(R.id.surname);
    TextView name = (TextView) v.findViewById(R.id.name);
    TextView email = (TextView) v.findViewById(R.id.email);
 
    if (type == 0) {
        ImageView img = (ImageView) v.findViewById(R.id.img);
        img.setImageResource(c.imageId);
    }
 
    surname.setText(c.surname);
    name.setText(c.name);
    email.setText(c.email);
 
    return v;
}

Завершение приложения

Теперь у нас есть наш специальный адаптер, который очень прост в использовании и привязывает его к ListView. В основной деятельности, которая содержит ListView:

1
2
3
4
5
6
7
8
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);
    ContactAdapter ca = new ContactAdapter(createContact(20), this);
    ListView lv = (ListView) findViewById(R.id.contact_list);
    lv.setAdapter(ca);
}
  • Исходный код скоро будет доступен.
Ссылка: Android Listview с многострочным макетом от нашего партнера JCG Франческо Аццолы из блога Surviving w / Android .