最近做了一個 app 而使用到 ExpandableListView, 這邊就紀錄下來如何使用.
下面是我的主 layout, 很簡單就只是一個 ExpandableListView 的 widiget.
activity_main.xml
ExpandableListView 有分 Group 和 Child, 因此分別對 Group 和 Child 設定各自的 View.
group_row.xml
child_row.xml
接下來就是主要程式的部份, 這邊我不使用 ExpandableListActivity, 原因是
在很多情況下直接繼承 (extend) ExpandableListActivity 是沒辦法, 比方說當你要使用 Fragment 的時候.
這邊為了簡化, 所以所有的 import 都不會列出來.
因為會使用到 ExpandableListView 這元件, 所以我們特別使用一個變數 (mExpandableListView) 來指向此元件.
public class MainActivity extends Activity {
private ExpandableListView mExpandableListView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mExpandableListView = (ExpandableListView) findViewById(R.id.elistview);
initData();
}
}
有了 ExpandableListView 元件, 接著必須把所需的資料放進此元件.
groupItems 使主要的群組, 而 childItems 是每個群組底下的資料
跟 ListView 一樣, 這邊定義一個 MyExpandListAdapter 來給 ExpandableListView 使用.
MyExpandListAdapter 會包含我們如何顯示每個行(row)資料和呈現的畫面.
private void initData() {
final String[] groupItems = { "Group1", "Group2", "Group3", "Group4", "Group5", };
final String[] childItems = { "Child1", "Child2", "Child3", "Child4", "Child5", };
MyExpandListAdapter adapter = new MyExpandListAdapter(this, groupItems);
int i = 0;
int count = groupItems.length;
/**
* add child data to groups
*/
for (i = 0; i < count; i++) {
adapter.addChild(i, childItems);
}
mExpandableListView.setAdapter(adapter);
}
MyExpandListAdapter 比較複雜, 因為這個主要是用來顯示資料並且在 ExpandableListView 裡的畫面呈現.
class MyExpandListAdapter extends BaseExpandableListAdapter {
Context ctxt = null;
/**
* Use SparseArray to store my group-child mapping datas,
*/
SparseArray data = new SparseArray();
String[] groups = null;
public MyExpandListAdapter(Context c, String[] groupitems) {
super();
ctxt = c;
groups = groupitems;
}
@Override
public String getChild(int groupPosition, int childPosition) {
String[] childs = data.get(groupPosition);
if (childs == null) {
return null;
}
if (childPosition >= childs.length) {
return null;
}
return childs[childPosition];
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
/**
* in this function, we can customize our child view and show data.
*/
View row = convertView;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) ctxt
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.child_row, parent, false);
}
TextView tv = (TextView) row.findViewById(R.id.childlabel);
String child = getChild(groupPosition, childPosition);
if (child != null) {
tv.setText(child);
}
return row;
}
@Override
public int getChildrenCount(int groupPosition) {
String[] childs = data.get(groupPosition);
if (childs == null) {
return 0;
}
return childs.length;
}
@Override
public String getGroup(int groupPosition) {
if (groupPosition >= groups.length) {
return null;
}
return groups[groupPosition];
}
@Override
public int getGroupCount() {
return groups.length;
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
/**
* in this function, we can customize our group view and show data.
*/
View row = convertView;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) ctxt
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.group_row, parent, false);
}
TextView tv = (TextView) row.findViewById(R.id.grouplabel);
String group = getGroup(groupPosition);
if (group != null) {
tv.setText(group);
}
return row;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
/**
* If set to false, we can't click child item.
*/
return false;
}
public void addChild(int group, String[] childs) {
/**
* Add this function for us to add childs.
* It will overwrite previsou data
* But this is just an example.
*/
data.put(group, childs);
notifyDataSetChanged();
}
}
這樣就是基本的 ExpandListView 了. 以下是畫面呈現,
如果注意到的話, 群組的折疊圖示竟然重疊了.
修改一下 group_row 的 layout
修改後的結果如下
不過一般通常折疊的圖示都是在右邊, 所以再次修改一下把折疊圖示移到最右邊.
private void initData() {
final String[] groupItems = { "Group1", "Group2", "Group3", "Group4", "Group5", };
final String[] childItems = { "Child1", "Child2", "Child3", "Child4", "Child5", };
MyExpandListAdapter adapter = new MyExpandListAdapter(this, groupItems);
int i = 0;
int count = groupItems.length;
/**
* add child data to groups
*/
for (i = 0; i < count; i++) {
adapter.addChild(i, childItems);
}
setIndicatorToRight();
mExpandableListView.setAdapter(adapter);
mExpandableListView.setOnChildClickListener(new OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
MyExpandListAdapter adapter = (MyExpandListAdapter) parent
.getAdapter();
String group = adapter.getGroup(groupPosition);
String child = adapter.getChild(groupPosition, childPosition);
Toast.makeText(MainActivity.this, group + " - " + child,
Toast.LENGTH_SHORT).show();
return true;
}
});
}
private void setIndicatorToRight() {
final float scale = getResources().getDisplayMetrics().density;
/**
* Calcaulate device screen width in pixel
*/
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int width = metrics.widthPixels;
mExpandableListView.setIndicatorBounds(width - (int)(50 * scale),
width - (int)(10 * scale));
}
下面就是最終畫面的呈現
原始碼下載:
here