среда, 10 ноября 2010 г.

Выпадающие списки (Expandable lists). Часть 1

Иногда требуется отобразить информацию поделенную на  категории или группы. В этих случаях удобно использовать многоуровневые списки. Андроид поддерживает двухуровневые списки, состоящие из групп и элементов входящих в эти группы. Рассмотрим их подробнее.


Пример тут, частично переведено это, ну и исправлено(см ниже), дополнено и систематизировано мной.
Для начало необходимо унаследовать активити от класса ExpandableListActivity и добавить импорты:
import android.app.ExpandableListActivity;

import android.os.Bundle;

import android.widget.SimpleExpandableListAdapter;

import java.util.List;

import java.util.ArrayList;

import java.util.Map;

import java.util.HashMap;

public class ExpList extends ExpandableListActivity

А второе - привязать данные адаптером к ней. В качестве адаптера будем использовать SimpleExpandableListAdapter 
SimpleExpandableListAdapter expListAdapter =
new SimpleExpandableListAdapter(
this,
createGroupList(), // создание групп(узлов или "шапки")
R.layout.grouprow, // слой для отображение любой из группы(на рисунке - со стрелкой)
String[] { "colorName" }, // массив ключей для вывода на экран
new int[] { R.id.groupname }, // Идентификатор в слое соответствующий TextView 
\\ по ссылке там ошибка как раз в исходниках, - автор описался и влепил идентификатор,
\\ который отсутствует в слое
createChildList(), // создание списка самих элементов 
R.layout.childrow, // слой для отображения каждого элемента(на рисунке - там где коды цветов)
new String[] { "shadeName", "rgb" }, // массив ключей для вывода на экран данных 
new int[] { R.id.childname, R.id.rgb } // идентификаторы двух вьюверов(TextView в данном случае) так же для отображения
);
В данном примере конструктор адаптера требует в качестве входных параметров:
1. контекст
Для групп:
2. Лист карт ключ-значение для групп, он создается в методе createGroupList()
3. Идентификатор слоя, который будет отображать группу
4. Массив ключей из карт из пункта 2, которые будут отображаться в списке
5. Массив идентификаторов вьюверов в разметке слоя из пункта 3, обратите внимания, что тут учитывается их последовательность и соответствие ключам из пункта 4
Для самих элементов:
6. Лист листов карт ключ-значение для элементов, он также создается в отдельном методе
7. Идентификатор слоя, который будет отображать элемент
8. Массив ключей из пункта 6, которые должны будут отображаться
9. Массив идентификаторов вьюверов из разметки слоя из пункта 7, так же тут должна быть их строгая последовательность и соответствие последовательность в пункте 8.

Теперь необходимо создать два вспомогательных метода - createGroupList() createChildList(), ничего сложного в них нет. Код для createGroupList():
private List createGroupList() {

   ArrayList result = new ArrayList();
// результирующий список
   for( int i = 0 ; i < colors.length ; ++i ) {

  HashMap m = new HashMap();
// создание карты
     m.put( "colorName",colors[i] );
//  в данном примере добавляется только одна строка
// соответствующая цвету и имеющая ключ colorName
  result.add( m );

   }

   return (List)result;

    }
Соответственно код для createChildList():
private List createChildList() {

 ArrayList result = new ArrayList();

 for( int i = 0 ; i < shades.length ; ++i ) {

   ArrayList secList = new ArrayList();

   for( int n = 0 ; n < shades[i].length ; n += 2 ) {

     HashMap child = new HashMap();

// в данном случае добавляются два значения и они же будут выводиться на экран,
// но ничего не мешает сделать их невидимыми, а использовать в сужебных целях
// например при обработки нажатия на элемент, тоже распространяется и для групп)
            child.put( "shadeName", shades[i][n] );

     child.put( "rgb", shades[i][n+1] );

  secList.add( child );

   }

   result.add( secList );

 }

 return result;

  }
С кодом всё, остается описать разметку и входные данные. Разметка для отображения группы состоит из одного вьювера - TextView:

Следует обратить внимание на отступ слева, он необходим чтобы галочка не наезжала на вьювер. Разметка для отображения элемента по сложнее - состоит из линейного слоя и двух TextView'ров в нем:




Исходные данные задаются в коде:
static final String colors[] = {

   "grey",

   "blue",

   "yellow",

   "red"

 };



 static final String shades[][] = {

   {

  "lightgrey","#D3D3D3",

  "dimgray","#696969",

  "sgi gray 92","#EAEAEA"

   },


   {

  "dodgerblue 2","#1C86EE",

  "steelblue 2","#5CACEE",

  "powderblue","#B0E0E6"

   },


   {

  "yellow 1","#FFFF00",

  "gold 1","#FFD700",

  "darkgoldenrod 1"," #FFB90F"

   },


   {

  "indianred 1","#FF6A6A",

  "firebrick 1","#FF3030",

  "maroon","#800000"

   }

    };

Комментариев нет:

Отправить комментарий