Обзор адаптеров (часть 1)

Содержание

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

В первом уроке “Задачи сотруднику” уже приводился пример создания адаптера (MetaArrayAdapter) для отображения списка задач, сейчас рассмотрим этот и другие адаптеры из состава FBA более детально.

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

Схема иерархии адаптеров FBA

Все адаптеры расположены в пакете ru.profi1c.engine.widget.

В текущей версии FBA разработчик может использовать 7 различных адаптеров. 5 из них предназначены для отображения линейных списков (MetaCursorAdapter, MetaArrayAdapter, SimpleHierarchyAdapter, HierarchyAdapter,PresentationAdapter) несмотря на присутствие в имени у некоторых слова «Hierarchy». Для двух-уровневой иерархии типа «родитель – подчинённые» предназначены адаптеры MetaExpandableListAdapter и  ParentExpandableCursorAdapter. MetaExpandableCursorAdapter абстрактный класс.

Совет по UI

Попытка реализовать выбор из иерархического справочника так же, как он сделан в 1С (последовательное открытие дочерних групп) не самая лучшая идея. Это и дополнительные сложности для разработчика, и неудобство для пользователя. Поставьте себя на место вашего пользователя и посчитайте, сколько кликов ему придется сделать, чтобы выбрать элемент на 3-4 уровне иерархии? А на мобильном устройстве небольшого размера ему придется еще скролить список при большом количестве элементов.

Одним из вариантов решения может быть следующий «выбор в два клика». На «форме» отображается линейный список, который фильтруется по выбранной группе из выпадающего списка.

Если количество элементов, отображаемых в списке, превышает 2-3 экрана можно дополнительно установить фильтрацию (например, поиском по наименованию). FBA Toolkit позволяет реализовать такой вариант довольно легко.

PresentationAdapter

Самый простой вариант адаптера. Предназначен для отображения списков объектов реализующих интерфейс IPresentation. Это справочники, документы и перечисления. Как правило, используется при выборе реквизита объекта ссылочного типа из выпадающих списков.

1
2
3
4
5
6
7
8
//1. выбор значения перечисления
//макет содержит Spinner с android:id="@+id/spinEnum1"
Spinner spin = (Spinner) findViewById(R.id.spinEnum1);
spin.setAdapter(new PresentationAdapter(this,EnumStavkiNDS.values()));
 
//...
//получить выбранное значение
EnumStavkiNDS enumSelected = (EnumStavkiNDS) spin.getSelectedItem();
//1. выбор значения перечисления
//макет содержит Spinner с android:id="@+id/spinEnum1"
Spinner spin = (Spinner) findViewById(R.id.spinEnum1);
spin.setAdapter(new PresentationAdapter(this,EnumStavkiNDS.values()));

//...
//получить выбранное значение
EnumStavkiNDS enumSelected = (EnumStavkiNDS) spin.getSelectedItem();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//2. Выбор элемента справочника. Контекст - FbaDBActivity
//Для отображения элементов в выпадающем списке используется кастомный макет (layout).
//Показан обработчик выбора элемента.
 
final Spinner spi2 = (Spinner) findViewById(R.id.spinCatalog1);
 
try {
    CatalogOrganizaciiDao dao = getHelper().getDao(CatalogOrganizacii.class);
    List<IPresentation> lst = dao.toPresentationList(dao.select());
 
    PresentationAdapter adapter = new PresentationAdapter(this, R.layout.test_row_layout, R.id.textView1,lst);
    spi2.setAdapter(adapter);
    spi2.setOnItemSelectedListener(new OnItemSelectedListener() {
 
        @Override
        public void onItemSelected(AdapterView<?> parent, View view,int position, long id) {
                CatalogOrganizacii catalog = (CatalogOrganizacii) spi2.getAdapter().getItem(position);
                Dbg.log(TAG+", catalog.ref = " + catalog.toString());
            }
    });
 
} catch (SQLException e) {
    e.printStackTrace();
}
//2. Выбор элемента справочника. Контекст - FbaDBActivity
//Для отображения элементов в выпадающем списке используется кастомный макет (layout).
//Показан обработчик выбора элемента.

final Spinner spi2 = (Spinner) findViewById(R.id.spinCatalog1);

try {
   	CatalogOrganizaciiDao dao = getHelper().getDao(CatalogOrganizacii.class);
   	List<IPresentation> lst = dao.toPresentationList(dao.select());

   	PresentationAdapter adapter = new PresentationAdapter(this, R.layout.test_row_layout, R.id.textView1,lst);
   	spi2.setAdapter(adapter);
   	spi2.setOnItemSelectedListener(new OnItemSelectedListener() {

   	   	@Override
   	   	public void onItemSelected(AdapterView<?> parent, View view,int position, long id) {
   	          	CatalogOrganizacii catalog = (CatalogOrganizacii) spi2.getAdapter().getItem(position);
   	          	Dbg.log(TAG+", catalog.ref = " + catalog.toString());
          	}
   	});

} catch (SQLException e) {
   	e.printStackTrace();
}

Содержание макета res\layout\test_row_layout.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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" >
 
    <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Medium Text"
        android:textColor="@android:color/white" />
 
</LinearLayout>
<?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" >

	<TextView
    	android:id="@+id/textView1"
    	android:layout_width="match_parent"
    	android:layout_height="wrap_content"
    	android:text="Medium Text"
    	android:textColor="@android:color/white" />

</LinearLayout>

Данные могут быть дополнительно отфильтрованы. Например, показать только организации, у которых в представлении есть «ООО»:

1
adapter.getFilter().filter("ооо");
adapter.getFilter().filter("ооо");

Чтобы снять фильтр укажите пустую строку или null.

MetaArrayAdapter

Основной адаптер для отображения небольших списков (элементов справочника, документов). Достоинство и одновременно недостаток данного адаптера в том, что данные для него должны быть считаны при создании. Если в списке ожидается большое количество элементов (более 50-100), то процесс формирования списка может занять продолжительное время + загрузка оперативной памяти приложения.

Плюс в том, что изменение объекта может быть выполнено достаточно легко в т.ч. и в автоматическом режиме при использовании соответствующих связанных контролов (в примере «Задачи для сотрудника» используется FieldCheckBox для редактирования реквизита «complete»).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//1. Список организаций, отображается только реквизит «Код».
//Макетом для строк выступает предопределенный android.R.layout.simple_list_item_1
//и TextView на нем с идентификатором  android.R.id.text1
 
ListView list1 = (ListView) findViewById(R.id.listView1);
 
CatalogOrganizaciiDao dao = getHelper().getDao( CatalogOrganizacii.class);
 
MetaArrayAdapter<CatalogOrganizacii> maa = new MetaArrayAdapter<CatalogOrganizacii>(
    this, CatalogOrganizacii.class, dao.select(),
    android.R.layout.simple_list_item_1,
    new String[] { "code" }, new int[] { android.R.id.text1 });
 
list1.setAdapter(maa);
//1. Список организаций, отображается только реквизит «Код».
//Макетом для строк выступает предопределенный android.R.layout.simple_list_item_1
//и TextView на нем с идентификатором  android.R.id.text1

ListView list1 = (ListView) findViewById(R.id.listView1);

CatalogOrganizaciiDao dao = getHelper().getDao( CatalogOrganizacii.class);

MetaArrayAdapter<CatalogOrganizacii> maa = new MetaArrayAdapter<CatalogOrganizacii>(
   	this, CatalogOrganizacii.class, dao.select(),
   	android.R.layout.simple_list_item_1,
   	new String[] { "code" }, new int[] { android.R.id.text1 });

list1.setAdapter(maa);

Описание параметров используемого конструктора см. в документации.

1
2
3
4
5
6
7
8
9
10
11
12
13
//2. Справочник "Единицы измерения". Как макет строки используется пользовательский макет R.layout.test_row_meta_adapter
//определенный в ресурсах приложения, содержит три view с идентификаторами R.id.tvCode, R.id.tvDesc, R.id.tvOther
//Выводятся предопределенные поля справочника "code","description" и пользовательское CatalogEdiniciIzmereniya.FIELD_NAME_KOEFFICIENT
//(в данном случае имя поля равно имени колонке в таблице)
 
CatalogEdiniciIzmereniyaDao dao2 = getHelper().getDao(CatalogEdiniciIzmereniya.class);
MetaArrayAdapter<CatalogEdiniciIzmereniya> maa2 = new MetaArrayAdapter<CatalogEdiniciIzmereniya>(
    this, CatalogEdiniciIzmereniya.class, dao2.select(),
    R.layout.test_row_meta_adapter, new String[] { "code","description",CatalogEdiniciIzmereniya.FIELD_NAME_KOEFFICIENT},
    new int[] { R.id.tvCode, R.id.tvDesc, R.id.tvOther });
 
ListView list1 = (ListView) findViewById(R.id.listView1);
list1.setAdapter(maa2);
//2. Справочник "Единицы измерения". Как макет строки используется пользовательский макет R.layout.test_row_meta_adapter
//определенный в ресурсах приложения, содержит три view с идентификаторами R.id.tvCode, R.id.tvDesc, R.id.tvOther
//Выводятся предопределенные поля справочника "code","description" и пользовательское CatalogEdiniciIzmereniya.FIELD_NAME_KOEFFICIENT
//(в данном случае имя поля равно имени колонке в таблице)

CatalogEdiniciIzmereniyaDao dao2 = getHelper().getDao(CatalogEdiniciIzmereniya.class);
MetaArrayAdapter<CatalogEdiniciIzmereniya> maa2 = new MetaArrayAdapter<CatalogEdiniciIzmereniya>(
   	this, CatalogEdiniciIzmereniya.class, dao2.select(),
   	R.layout.test_row_meta_adapter, new String[] { "code","description",CatalogEdiniciIzmereniya.FIELD_NAME_KOEFFICIENT},
   	new int[] { R.id.tvCode, R.id.tvDesc, R.id.tvOther });

ListView list1 = (ListView) findViewById(R.id.listView1);
list1.setAdapter(maa2);

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//3. Справочник «Номенклатура» с отбором по услугам.
// Отображаются 3 реквизита: «Наименование», «Ставка НДС» и признак услуги как флажок. //Используется кастомный макет для отображения, переопределяется вывод наименования и устанавливается свой обработчик на флажок.
 
//Получение данных для списка
CatalogNomenklaturaDao daoSku = getHelper().getDao(CatalogNomenklatura.class);
CatalogNomenklatura parent = daoSku.findByDescription("Услуги");
List<CatalogNomenklatura> lst = daoSku.select(parent);
 
//Кастомный построитель /форматтер для элементов строки
MetaAdapterViewBinder adapterBinder = new MetaAdapterViewBinder(
    this, CatalogNomenklatura.class, new String[] {
            CatalogNomenklatura.FIELD_NAME_DESCRIPTION,
            CatalogNomenklatura.FIELD_NAME_STAVKA_NDS,
            CatalogNomenklatura.FIELD_NAME_USLUGA, },
    new int[] { R.id.tvCaption, R.id.tvOther, R.id.cbUsluga });
adapterBinder.setViewBinder(skuViewBinder);
 
MetaArrayAdapter<CatalogNomenklatura> maaSku = new MetaArrayAdapter<CatalogNomenklatura>(
    lst, R.layout.test_row_sku, adapterBinder);
 
listSku = (ListView) findViewById(R.id.listView2);
listSku.setAdapter(maaSku);
//3. Справочник «Номенклатура» с отбором по услугам.
// Отображаются 3 реквизита: «Наименование», «Ставка НДС» и признак услуги как флажок. //Используется кастомный макет для отображения, переопределяется вывод наименования и устанавливается свой обработчик на флажок.

//Получение данных для списка
CatalogNomenklaturaDao daoSku = getHelper().getDao(CatalogNomenklatura.class);
CatalogNomenklatura parent = daoSku.findByDescription("Услуги");
List<CatalogNomenklatura> lst = daoSku.select(parent);

//Кастомный построитель /форматтер для элементов строки
MetaAdapterViewBinder adapterBinder = new MetaAdapterViewBinder(
   	this, CatalogNomenklatura.class, new String[] {
          	CatalogNomenklatura.FIELD_NAME_DESCRIPTION,
          	CatalogNomenklatura.FIELD_NAME_STAVKA_NDS,
          	CatalogNomenklatura.FIELD_NAME_USLUGA, },
   	new int[] { R.id.tvCaption, R.id.tvOther, R.id.cbUsluga });
adapterBinder.setViewBinder(skuViewBinder);

MetaArrayAdapter<CatalogNomenklatura> maaSku = new MetaArrayAdapter<CatalogNomenklatura>(
   	lst, R.layout.test_row_sku, adapterBinder);

listSku = (ListView) findViewById(R.id.listView2);
listSku.setAdapter(maaSku);

Макет test_row_sku.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?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="fill_parent"
    android:orientation="horizontal"
    android:padding="10dp" >
 
    <TextView
        android:id="@+id/tvCaption"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="4"
        android:gravity="center_vertical"
        android:text="TextView" />
 
    <TextView
        android:id="@+id/tvOther"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView" />
 
    <CheckBox
        android:id="@+id/cbUsluga"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false"
        android:text="Услуга" />
 
</LinearLayout>
<?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="fill_parent"
	android:orientation="horizontal"
	android:padding="10dp" >

	<TextView
    	android:id="@+id/tvCaption"
    	android:layout_width="wrap_content"
    	android:layout_height="match_parent"
    	android:layout_weight="4"
    	android:gravity="center_vertical"
    	android:text="TextView" />

	<TextView
    	android:id="@+id/tvOther"
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:text="TextView" />

	<CheckBox
    	android:id="@+id/cbUsluga"
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:focusable="false"
    	android:text="Услуга" />

</LinearLayout>
1
2
3
4
5
6
7
8
9
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
50
51
52
53
54
/*
 * кастомное форматирование поля,связь элементов отображения с данными (обработчики событий изменения)
 */
private MetaAdapterViewBinder.ViewBinder skuViewBinder = new MetaAdapterViewBinder.ViewBinder() {
 
    @Override
    public boolean setViewValue(View v, Cursor cursor, Field field) {
            return false;
    }
 
    @Override
    public boolean setViewValue(View v, Object item, Field field) {
 
            CatalogNomenklatura ref = (CatalogNomenklatura) item;
            final String name = field.getName();
 
            if(CatalogNomenklatura.FIELD_NAME_DESCRIPTION.equalsIgnoreCase(name)){
                    StringBuilder sb = new StringBuilder();
                    int level = ref.getLevel();
                    for(int i = 0; i< level;i++)
                        sb.append("-");
                        ((TextView)v).setText(sb.toString() + " " + ref.getDescription());
                    return true;
            }
            return false;
    }
 
    @Override
    public BaseViewHolder createViewHolder(View root) {
 
            SkuViewHolder holder = new SkuViewHolder(root);
            //по клику на чек-бокс изменяем значение в связанном элементе адаптера
            //внимание! сам элемент здесь не сохраняется в базу данных
            holder.cbUsluga.setOnClickListener(new OnClickListener() {
 
                    @Override
                    public void onClick(View v) {
                        CheckBox cb = (CheckBox) v;
                        int pos = (Integer) cb.getTag();
                        CatalogNomenklatura ref = (CatalogNomenklatura) listSku.getItemAtPosition(pos);
                        ref.usluga = cb.isChecked();
                        ref.setModified(true);
 
                    }
            });
            return holder;
    }
 
    @Override
    public void onBind(BaseViewHolder viewHolder, int position) {
            SkuViewHolder holder = (SkuViewHolder) viewHolder;
            holder.cbUsluga.setTag(position);
    }
};
/*
 * кастомное форматирование поля,связь элементов отображения с данными (обработчики событий изменения)
 */
private MetaAdapterViewBinder.ViewBinder skuViewBinder = new MetaAdapterViewBinder.ViewBinder() {

   	@Override
   	public boolean setViewValue(View v, Cursor cursor, Field field) {
          	return false;
   	}

   	@Override
   	public boolean setViewValue(View v, Object item, Field field) {

          	CatalogNomenklatura ref = (CatalogNomenklatura) item;
          	final String name = field.getName();

          	if(CatalogNomenklatura.FIELD_NAME_DESCRIPTION.equalsIgnoreCase(name)){
                 	StringBuilder sb = new StringBuilder();
                 	int level = ref.getLevel();
                 	for(int i = 0; i< level;i++)
                       	sb.append("-");
                       	((TextView)v).setText(sb.toString() + " " + ref.getDescription());
                 	return true;
          	}
          	return false;
   	}

   	@Override
   	public BaseViewHolder createViewHolder(View root) {

          	SkuViewHolder holder = new SkuViewHolder(root);
          	//по клику на чек-бокс изменяем значение в связанном элементе адаптера
          	//внимание! сам элемент здесь не сохраняется в базу данных
          	holder.cbUsluga.setOnClickListener(new OnClickListener() {

                 	@Override
                 	public void onClick(View v) {
                       	CheckBox cb = (CheckBox) v;
                       	int pos = (Integer) cb.getTag();
                       	CatalogNomenklatura ref = (CatalogNomenklatura) listSku.getItemAtPosition(pos);
                       	ref.usluga = cb.isChecked();
                       	ref.setModified(true);

                 	}
          	});
          	return holder;
   	}

   	@Override
   	public void onBind(BaseViewHolder viewHolder, int position) {
          	SkuViewHolder holder = (SkuViewHolder) viewHolder;
          	holder.cbUsluga.setTag(position);
   	}
};

Класс, отвечающий за форматирование дочерних элементов списка. Порядок вызова обработчиков:
1 createViewHolder – при создании View для строки адаптера
2 onBind – после создания и при повторном связывании строки. Здесь желательно сохранять индекс позиции на которую связывается строка, пригодится для доступа к элементам адаптера.
3. setViewValue – при отображении дочернего поля строки. Здесь можно выполнить форматирование. Если адаптер на базе списка будет вызван обработчик setViewValue(View v, Object item, Field field) для адаптеров на базе курсора – setViewValue(View v, Cursor cursor, Field field)  

И реализация модели ViewHolder для строк:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * ViewHolder паттерн для эффективной работы со строками адаптеров
 */
private static class SkuViewHolder extends BaseViewHolder {
 
    private TextView tvCaption;
    private TextView tvOther;
    private CheckBox cbUsluga;
 
    public SkuViewHolder(View root) {
            super(root);
 
            tvCaption = (TextView) root.findViewById(R.id.tvCaption);
            tvOther = (TextView) root.findViewById(R.id.tvOther);
            cbUsluga = (CheckBox) root.findViewById(R.id.cbUsluga);
    }
 
    @Override
    public View getViewById(int id) {
            switch(id){
            case R.id.tvCaption:
                    return tvCaption;
            case R.id.tvOther:
                    return tvOther;
            case R.id.cbUsluga:
                    return cbUsluga;
            }
            return null;
    }
 
}
/*
 * ViewHolder паттерн для эффективной работы со строками адаптеров
 */
private static class SkuViewHolder extends BaseViewHolder {

   	private TextView tvCaption;
   	private TextView tvOther;
   	private CheckBox cbUsluga;

   	public SkuViewHolder(View root) {
          	super(root);

          	tvCaption = (TextView) root.findViewById(R.id.tvCaption);
          	tvOther = (TextView) root.findViewById(R.id.tvOther);
          	cbUsluga = (CheckBox) root.findViewById(R.id.cbUsluga);
   	}

   	@Override
   	public View getViewById(int id) {
          	switch(id){
          	case R.id.tvCaption:
                 	return tvCaption;
          	case R.id.tvOther:
                 	return tvOther;
          	case R.id.cbUsluga:
                 	return cbUsluga;
          	}
          	return null;
   	}

}

Результат:

К списку может быть применен  динамический отбор (фильтрация) по представлению,  если допустимо приведение значение коллекции к List<IPresentation>, т.е если отображается список элементов справочника или список документов.

1
maaSku.getFilter().filter("расходы");
maaSku.getFilter().filter("расходы");

MetaCursorAdapter

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

Вывод предыдущего примера с использованием курсора:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CatalogNomenklaturaDao daoSku = getHelper().getDao(CatalogNomenklatura.class);
CatalogNomenklatura parent = daoSku.findByDescription("Услуги");
Cursor cursor2 = daoSku.selectCursor(parent);
 
startManagingCursor(cursor2);
 
//Кастомный построитель /форматтер для элементов строки
MetaAdapterViewBinder adapterBinder = new MetaAdapterViewBinder(
    this, CatalogNomenklatura.class, new String[] {
            CatalogNomenklatura.FIELD_NAME_DESCRIPTION,
            CatalogNomenklatura.FIELD_NAME_STAVKA_NDS,
            CatalogNomenklatura.FIELD_NAME_USLUGA, },
    new int[] { R.id.tvCaption, R.id.tvOther, R.id.cbUsluga });
adapterBinder.setViewBinder(skuViewBinder);
 
MetaCursorAdapter mca2 = new MetaCursorAdapter(this, cursor2, R.layout.test_row_sku, adapterBinder);
 
listSku = (ListView) findViewById(R.id.listView2);
listSku.setAdapter(mca2);
CatalogNomenklaturaDao daoSku = getHelper().getDao(CatalogNomenklatura.class);
CatalogNomenklatura parent = daoSku.findByDescription("Услуги");
Cursor cursor2 = daoSku.selectCursor(parent);

startManagingCursor(cursor2);

//Кастомный построитель /форматтер для элементов строки
MetaAdapterViewBinder adapterBinder = new MetaAdapterViewBinder(
   	this, CatalogNomenklatura.class, new String[] {
          	CatalogNomenklatura.FIELD_NAME_DESCRIPTION,
          	CatalogNomenklatura.FIELD_NAME_STAVKA_NDS,
          	CatalogNomenklatura.FIELD_NAME_USLUGA, },
   	new int[] { R.id.tvCaption, R.id.tvOther, R.id.cbUsluga });
adapterBinder.setViewBinder(skuViewBinder);

MetaCursorAdapter mca2 = new MetaCursorAdapter(this, cursor2, R.layout.test_row_sku, adapterBinder);

listSku = (ListView) findViewById(R.id.listView2);
listSku.setAdapter(mca2);
1
2
3
4
5
6
7
8
9
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/*
 * кастомное форматирование поля,связь элементов отображения с данными (обработчики событий изменения)
 */
private MetaAdapterViewBinder.ViewBinder skuViewBinder = new MetaAdapterViewBinder.ViewBinder() {
 
    //кастомное форматирование поля
    @Override
    public boolean setViewValue(View v, Cursor cursor, Field field) {
 
            final String name = field.getName();
            if(CatalogNomenklatura.FIELD_NAME_DESCRIPTION.equalsIgnoreCase(name)){
 
                    int level = 0;
                    String desc  ="";
                    //Получить индексы  колонок и значение по ним
                    int colIndex = Сursor.getColumnIndex(CatalogNomenklatura.FIELD_NAME_LEVEL);
                    if(colIndex!=-1)
                        level = cursor.getInt(colIndex);
                    colIndex = cursor.getColumnIndex(CatalogNomenklatura.FIELD_NAME_DESCRIPTION);
                    if(colIndex!=-1)
                        desc = cursor.getString(colIndex);
 
                    StringBuilder sb = new StringBuilder();
                    for(int i = 0; i< level;i++)
                        sb.append("-");
                    ((TextView)v).setText(sb.toString() + " " + desc);
                    return true;
            }
            return false;
    }
 
    @Override
    public boolean setViewValue(View v, Object item, Field field) {
            return false;
    }
 
    @Override
    public BaseViewHolder createViewHolder(View root) {
 
            SkuViewHolder holder = new SkuViewHolder(root);
 
            //по клику на чек-бокс изменяем значение в связанном элементе адаптера
            //внимание! сам элемент здесь не сохраняется в базу данных
            holder.cbUsluga.setOnClickListener(new OnClickListener() {
 
                    @Override
                    public void onClick(View v) {
                        CheckBox cb = (CheckBox) v;
 
                        int pos = (Integer) cb.getTag();
                        Cursor c = (Cursor) listSku.getItemAtPosition(pos);
 
                        int columnIndex = c.getColumnIndex(CatalogNomenklatura.FIELD_NAME_REF);
                        if(columnIndex!=-1){
                                String ref = c.getString(columnIndex);
                                Dbg.log(TAG+" SKU ref = " + ref);
                                // Теперь по идентификатору например можно найти элемент
                                // в справочнике и обновить его
 
                                // Курсор автоматически не обновляется, при обновлении
                                // данных вы должны обновить его самостоятельно
                        }
                        }
            });
            return holder;
    }
 
    @Override
    public void onBind(BaseViewHolder viewHolder, int position) {
            SkuViewHolder holder = (SkuViewHolder) viewHolder;
            holder.cbUsluga.setTag(position);
    }
};
 
// идентичен предыдущему примеру
private static class SkuViewHolder extends BaseViewHolder {
    // идентичен предыдущему примеру
}
/*
 * кастомное форматирование поля,связь элементов отображения с данными (обработчики событий изменения)
 */
private MetaAdapterViewBinder.ViewBinder skuViewBinder = new MetaAdapterViewBinder.ViewBinder() {

   	//кастомное форматирование поля
   	@Override
   	public boolean setViewValue(View v, Cursor cursor, Field field) {

          	final String name = field.getName();
          	if(CatalogNomenklatura.FIELD_NAME_DESCRIPTION.equalsIgnoreCase(name)){

                 	int level = 0;
                 	String desc  ="";
                 	//Получить индексы  колонок и значение по ним
                 	int colIndex = Сursor.getColumnIndex(CatalogNomenklatura.FIELD_NAME_LEVEL);
                 	if(colIndex!=-1)
                       	level = cursor.getInt(colIndex);
                 	colIndex = cursor.getColumnIndex(CatalogNomenklatura.FIELD_NAME_DESCRIPTION);
                 	if(colIndex!=-1)
                       	desc = cursor.getString(colIndex);

                 	StringBuilder sb = new StringBuilder();
                 	for(int i = 0; i< level;i++)
                       	sb.append("-");
                 	((TextView)v).setText(sb.toString() + " " + desc);
                 	return true;
          	}
          	return false;
   	}

   	@Override
   	public boolean setViewValue(View v, Object item, Field field) {
          	return false;
   	}

   	@Override
   	public BaseViewHolder createViewHolder(View root) {

          	SkuViewHolder holder = new SkuViewHolder(root);

          	//по клику на чек-бокс изменяем значение в связанном элементе адаптера
          	//внимание! сам элемент здесь не сохраняется в базу данных
          	holder.cbUsluga.setOnClickListener(new OnClickListener() {

                 	@Override
                 	public void onClick(View v) {
                       	CheckBox cb = (CheckBox) v;

                       	int pos = (Integer) cb.getTag();
                       	Cursor c = (Cursor) listSku.getItemAtPosition(pos);

                       	int columnIndex = c.getColumnIndex(CatalogNomenklatura.FIELD_NAME_REF);
                       	if(columnIndex!=-1){
                              	String ref = c.getString(columnIndex);
                              	Dbg.log(TAG+" SKU ref = " + ref);
                              	// Теперь по идентификатору например можно найти элемент
                              	// в справочнике и обновить его

                              	// Курсор автоматически не обновляется, при обновлении
                              	// данных вы должны обновить его самостоятельно
                       	}
                       	}
          	});
          	return holder;
   	}

   	@Override
   	public void onBind(BaseViewHolder viewHolder, int position) {
          	SkuViewHolder holder = (SkuViewHolder) viewHolder;
          	holder.cbUsluga.setTag(position);
   	}
};

// идентичен предыдущему примеру
private static class SkuViewHolder extends BaseViewHolder {
   	// идентичен предыдущему примеру
}

Часть 2

Похожие записи: