В этом уроке:

- используем свой SimpleAdapter.ViewBinder

 

Адаптер SimpleAdapter при своей работе сопоставляет View-компоненты и значения из Map-объектов. Как он это делает по умолчанию и с каким View-компонентами умеет работать, мы рассмотрели в предыдущих уроках. Но если нам не хватает этих возможностей, мы всегда можем создать свой обработчик и присвоить его адаптеру.

Для этого используется метод setViewBinder (SimpleAdapter.ViewBinder viewBinder), который на вход требует объект SimpleAdapter.ViewBinder. Мы создаем свой вариант этого биндера и реализуем в нем метод setViewValue(View view, Object data, String textRepresentation), в котором прописываем всю логику сопоставления данных и компонентов (биндинга). Метод возвращает значение boolean.

 

Алгоритм работы адаптера таков: он сначала проверяет, давали ли ему сторонний биндер.

Если находит, то выполняет его метод setViewValue. Если метод возвращает true, то адаптер считает, что обработка успешно завершена, если же false – то он выполняет биндинг в своем стандартном алгоритме, который мы рассмотрели на предыдущих уроках.

Если адаптер не находит сторонний биндер, он также выполняет стандартный биндинг.

Т.е. наша задача – заполнить метод SimpleAdapter.ViewBinder.setViewValue. И здесь уже нет ограничений на TextView или ImageView,  может быть обработан и заполнен любой компонент. Создадим пример, в котором будем заполнять значение ProgressBar и менять цвет LinearLayout.

Это будет приложение-мониторинг, которое отображает уровень загрузки мощностей какой-то системы в разрезе дней. ProgressBar будет показывать уровень загрузки, а весь пункт списка будет подкрашиваться цветом в зависимости от уровня загрузки.

 

Создадим проект:

Project name: P0501_SimpleAdapterCustom2
Build Target: Android 2.3.3
Application name: SimpleAdapterCustom2
Package name: ru.startandroid.develop.p0501simpleadaptercustom2
Create Activity: MainActivity

 

Рисуем экран main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <ListView
        android:id="@+id/lvSimple"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>
</LinearLayout> 

Только список.

 

Нам понадобится создать файл res/values/colors.xml, где мы перечислим требуемые нам цвета:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="Bckgr">#9C9C9C</color>
    <color name="Red">#33FF0000</color>
    <color name="Orange">#33FFFF00</color>
    <color name="Green">#3300FF00</color>
    <color name="Black">#000000</color>
</resources>

 

Теперь создаем layout для пунктов списка res/layout/item.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:orientation="vertical"
    android:background="@color/Bckgr">
    <LinearLayout
        android:id="@+id/llLoad"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:id="@+id/tvLoad"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView"
            android:layout_gravity="center_horizontal"
            android:textColor="@color/Black">
        </TextView>
        <ProgressBar
            android:id="@+id/pbLoad"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:max="100">
        </ProgressBar>
    </LinearLayout>
</LinearLayout>

llLoad – LinearLayout который занимает весь пункт списка, и который мы будем разукрашивать,
tvLoad – текст-инфа,
pbLoad – индикатор загрузки.

 

Код MainActivity.java:

package ru.startandroid.develop.p0501simpleadaptercustom2;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SimpleAdapter;

public class MainActivity extends Activity {

  // имена атрибутов для Map
  final String ATTRIBUTE_NAME_TEXT = "text";
  final String ATTRIBUTE_NAME_PB = "pb";
  final String ATTRIBUTE_NAME_LL = "ll";

  ListView lvSimple;

  /** Called when the activity is first created. */
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // массив данных
    int load[] = { 41, 48, 22, 35, 30, 67, 51, 88 };

    // упаковываем данные в понятную для адаптера структуру
    ArrayList<Map<String, Object>> data = new ArrayList<Map<String, Object>>(
        load.length);
    Map<String, Object> m;
    for (int i = 0; i < load.length; i++) {
      m = new HashMap<String, Object>();
      m.put(ATTRIBUTE_NAME_TEXT, "Day " + (i+1) + ". Load: " + load[i] + "%");
      m.put(ATTRIBUTE_NAME_PB, load[i]);
      m.put(ATTRIBUTE_NAME_LL, load[i]);
      data.add(m);
    }

    // массив имен атрибутов, из которых будут читаться данные
    String[] from = { ATTRIBUTE_NAME_TEXT, ATTRIBUTE_NAME_PB,
        ATTRIBUTE_NAME_LL };
    // массив ID View-компонентов, в которые будут вставлять данные
    int[] to = { R.id.tvLoad, R.id.pbLoad, R.id.llLoad };

    // создаем адаптер
    SimpleAdapter sAdapter = new SimpleAdapter(this, data, R.layout.item,
        from, to);
    // Указываем адаптеру свой биндер
    sAdapter.setViewBinder(new MyViewBinder());

    // определяем список и присваиваем ему адаптер
    lvSimple = (ListView) findViewById(R.id.lvSimple);
    lvSimple.setAdapter(sAdapter);
  }

  class MyViewBinder implements SimpleAdapter.ViewBinder {
    
    int red = getResources().getColor(R.color.Red);
    int orange = getResources().getColor(R.color.Orange);
    int green = getResources().getColor(R.color.Green);
    
    @Override
    public boolean setViewValue(View view, Object data,
        String textRepresentation) {
      int i = 0;
      switch (view.getId()) {
      // LinearLayout
      case R.id.llLoad:
        i = ((Integer) data).intValue();
        if (i < 40) view.setBackgroundColor(green); else 
          if (i < 70) view.setBackgroundColor(orange); else
        view.setBackgroundColor(red);
        return true;
      // ProgressBar  
      case R.id.pbLoad:
        i = ((Integer) data).intValue();
        ((ProgressBar)view).setProgress(i);
        return true;
      }
      return false;
    }
  }
}

Смотрим код. Заполняем массив данных загрузки по 100-бальной шкале. Формируем данные для адаптера: в TextView будем передавать краткую информацию (String), а в ProgressBar и LinearLayout – значение загрузки (int). Заполняем массивы сопоставления, создаем адаптер, говорим ему, чтобы использовал наш биндер, и настраиваем список.

 

Вложенный класс MyViewBinder – это наша реализация биндера. Мы должны реализовать метод setViewValue, который будет использоваться адаптером для сопоставления данных из Map и View-компонентов. На вход ему идут:

view - View-компонент
data - данные для него
textRepresentation - текстовое представление данных (data.toString() или пустой String, но никогда не null)

Итак, смотрим реализацию. Сначала проверяется какой компонент нам дали на обработку.

В случае llLoad мы ожидаем данные типа int, поэтому выполняем приведение Object к Integer и получаем данные по загрузке из массива. А далее смотрим уровень этой загрузки. Если меньше 40, то будем считать, что все ок, цвет фона зеленый. От 40 до 70 – внимание, цвет желтый. Выше 70 – высокая нагрузка, красный цвет. Возвращаем true. Это важно! Тем самым мы говорим адаптеру, что мы успешно выполнили биндинг для данного компонента и выполнять для него стандартную обработку не надо.

В случае pbLoad мы также ожидаем int и выполняем приведение. А затем просто вызываем метод setProgress и передаем ему значение. В конце возвращаем true – мы сами успешно обработали компонент, стандартная обработка не нужна.

Для всех других View-компонентов метод setViewValue будет возвращать false. Это значит, компоненты пойдут на стандартную обработку адаптером. В нашем случае по этому пути отправится tvLoad и адаптер сам передаст ему текст из Map, наше вмешательство не нужно.

Все сохраняем и запускаем.

Получаем вот такую картинку. LinearLayout заполнился цветом, ProgressBar отобразил уровень загрузки, TextView показал информацию о дне и загрузке.

 

На следующем уроке:

- используем SimpleAdapter для построения списка
- добавляем и удаляем записи в списке

 


Присоединяйтесь к нам в Telegram:

- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance 

- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня




Language

Автор сайта

Дмитрий Виноградов

Подробнее можно посмотреть или почитать.

Никакие другие люди не имеют к этому сайту никакого отношения и просто занимаются плагиатом.

Социальные сети

 

В канале я публикую ссылки на интересные и полезные статьи по Android

В чате можно обсудить вопросы и проблемы, возникающие при разработке



Группа ВКонтакте



Поддержка проекта

Яндекс
410011180491924

WebMoney
R248743991365
Z551306702056

Paypal