如何使用ExpandableList

如果我們想要寫一個可以伸展的ListView的話,
可以使用google開發的新元件ExpandableList,
這個範例是ApiDemo的範例, 有興趣可以去參考看看。




由上圖可以清楚知道, 這個元件是由兩種資料所組成, 最上層的稱做Group,
而展開的資料是Child data,
一般來說, 我們可以了解到, 同性質的資料是可以歸類成一堆,
如果資料太多, 對於listview而言, 畫面會變得太冗長,
那如果利用轉頁的方式來呈現這些資料,
又顯得不是那麼一目了然。

因此Android開發了這樣的一個元件,
Expandable代表可延展、展開的意思, 只要利用這個元件,
可以輕鬆完成上面圖片所呈現的畫面。

在google給的範例中, 我們可以看到它利用繼承ExpandableListActivity這個類別,
讓我們不用再宣告一個ExpandableListView的元件,
便可以直接使用它。

public class ExpandableListViewDemo extends ExpandableListActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}

而我們在之前ListView知道, 通常會配置一個adapter來連結我們的list,
ExpandableListView也不例外, 來看一下ExpandableList的官方API,
http://developer.android.com/reference/android/widget/SimpleExpandableListAdapter.html


public SimpleExpandableListAdapter (Context context, List<? extends Map<String, ?>> groupData, int groupLayout, String[]groupFrom, int[] groupTo, List<? extends List<? extends Map<String, ?>>> childData, int childLayout, String[] childFrom, int[] childTo)

Since: API Level 1


Constructor
Parameters
contextThe context where the ExpandableListView associated with this SimpleExpandableListAdapter is running
groupDataA List of Maps. Each entry in the List corresponds to one group in the list. The Maps contain the data for each group, and should include all the entries specified in "groupFrom"
groupLayoutresource identifier of a view layout that defines the views for a group. The layout file should include at least those named views defined in "groupTo"
groupFromA list of keys that will be fetched from the Map associated with each group.
groupToThe group views that should display column in the "groupFrom" parameter. These should all be TextViews. The first N views in this list are given the values of the first N columns in the groupFrom parameter.
childDataA List of List of Maps. Each entry in the outer List corresponds to a group (index by group position), each entry in the inner List corresponds to a child within the group (index by child position), and the Map corresponds to the data for a child (index by values in the childFrom array). The Map contains the data for each child, and should include all the entries specified in "childFrom"
childLayoutresource identifier of a view layout that defines the views for a child. The layout file should include at least those named views defined in "childTo"
childFromA list of keys that will be fetched from the Map associated with each child.
childToThe child views that should display column in the "childFrom" parameter. These should all be TextViews. The first N views in this list are given the values of the first N columns in the childFrom parameter.


從建構子就可以知道, 這次的Adpater相當的複雜,
由於這個元件必須建立好Group與Child的資料,
因此需要兩個資料結構來完成, 而由建構子發現,
這兩個資料結構分別是List<Map<String, String>>與List<List<Map<String, String>>>,
所以我們就來建造一下這兩個資料結構內的資訊吧!

    private String[] lunch = {
     "飯類","麵類","小菜"
    };
    private String[][] lunch_class = {
     {"滷肉飯","雞腿飯","排骨飯","雞排飯","豬腳飯"},
     {"陽春麵","榨菜肉絲麵","餛飩麵","牛肉麵","乾麵"},
     {"豆干","豆腐","豬皮","海帶","滷蛋"}
    };

首先建立兩個陣列, 分別放groupData以及childData,
接著宣告groupData與childData的資料結構。
List<Map<String, String>> groupData = new ArrayList<Map<String, String>>();
List<List<Map<String, String>>> childData = new ArrayList<List<Map<String, Strng>>>();

利用迴圈, 將上面兩個陣列丟進去這兩個資料結構內。
for (int i = 0; i < lunch.length; i++) {
    Map<String, String> curGroupMap = new HashMap<String, String>();
    groupData.add(curGroupMap);
    curGroupMap.put(NAME, lunch[i]);
           
    List<Map<String, String>> children = new ArrayList<Map<String, String>>();
    for (int j = 0; j <lunch_class[i].length ; j++) {
        Map<String, String> curChildMap = new HashMap<String, String>();
        children.add(curChildMap);
        curChildMap.put(NAME, lunch_class[i][j]);
    }
    childData.add(children);
}

再來就把這兩個資料結構丟進去Adapter裡面。

          mAdapter = new SimpleExpandableListAdapter(

                this,
                groupData,
                android.R.layout.simple_expandable_list_item_1,
                new String[] { NAME },
                new int[] { android.R.id.text1 },
                childData,
                android.R.layout.simple_expandable_list_item_1,
                new String[] { NAME },
                new int[] { android.R.id.text1 }
          );


利用內鍵的xml進行排版。
最後將adapter塞入ExtendableListView就可以完成了。
setListAdapter(mAdapter);








程式碼
http://uploadingit.com/file/qoiwhygdjxlmvkei/ExpandableListViewDemo.zip