可擴展收納式的ListView,好處當然是可以讓APP的UI看起來更簡潔不占空間~
在官方的API文件中其實就可以看到有提供這種功能的API文件
ExpandableListView 官方 API 文件
"ExpandableListView"
網路稍微爬一下就可以看到很多範例,在這我們就做點小修正
成品圖大概長這樣~(展開前後圖)
主要分成幾個部分
1 . xml
2 . fragment
3 . adapter
====================== xml ======================
fragment中的layout中加入
<ExpandableListView android:id="@+id/lvExp" android:layout_height="match_parent" android:layout_width="match_parent"/>建立一個新的expandable_head.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/lblListHeader_head"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="@string/version"
android:textColor="#000000"
android:textSize="16sp" />
<TextView
android:id="@+id/lblListHeader_memo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/setting_system_version"
android:text="0.0.0"
android:textColor="#767676"
android:textSize="14sp" />
</LinearLayout>
<ImageView
android:id="@+id/img_list_close"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_alignParentRight="true"
android:src="@mipmap/ic_putup"/>
</RelativeLayout>
建立一個新的expandable_item.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="40dp"
android:orientation="vertical"
android:padding="8dp"
android:background="#FFFFFF">
<TextView
android:id="@+id/lblListItem_head"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"
android:textSize="16sp"
android:textColor="#767676" />
<TextView
android:id="@+id/lblListItem_memo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"
android:textSize="12sp"
android:textColor="#FF5722" />
<View
android:layout_width="match_parent"
android:layout_height="1dip"
android:background="#F2F2F2" />
</LinearLayout>
====================== adapter ======================
public class ExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private List listDataHeader; // header titles
// child data in format of header title, child title
private HashMap> listDataChild;
public ExpandableListAdapter(Context context, List listDataHeader,
HashMap> listChildData) {
this.context = context;
this.listDataHeader = listDataHeader;
this.listDataChild = listChildData;
}
@Override
public Object getChild(int groupPosition, int childPosititon) {
return this.listDataChild.get(this.listDataHeader.get(groupPosition))
.get(childPosititon);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final String childText = (String) getChild(groupPosition, childPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this.context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.f4_expandable_items, null);
}
String[] Child_array = childText.split("(,,,\\+)");
TextView txtListChild_head = (TextView) convertView.findViewById(R.id.lblListItem_head);
TextView txtListChild_memo = (TextView) convertView.findViewById(R.id.lblListItem_memo);
txtListChild_head.setTypeface(null, Typeface.BOLD);
txtListChild_memo.setTypeface(null, Typeface.BOLD);
txtListChild_head.setText(Child_array[0]);
txtListChild_memo.setText(Child_array[1]);
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return this.listDataChild.get(this.listDataHeader.get(groupPosition)).size();
}
@Override
public Object getGroup(int groupPosition) {
return this.listDataHeader.get(groupPosition);
}
@Override
public int getGroupCount() {
return this.listDataHeader.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String headerText = (String) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this.context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.f4_expandable_head, null);
}
isExpanded 判斷擴展的狀態 //在這邊加入Image 在Head點擊擴展時 右邊的圖片會做替換 ImageView HeaderRightIcon = (ImageView) convertView.findViewById(R.id.img_list_close); //
if(isExpanded){ HeaderRightIcon.setImageResource(R.mipmap.ic_putup); }else{ HeaderRightIcon.setImageResource(R.mipmap.ic_putaway); } String[] Header_array = headerText.split("(,,,\\+)"); TextView lblListHeader_head = (TextView) convertView.findViewById(R.id.lblListHeader_head); TextView lblListHeader_memo = (TextView) convertView.findViewById(R.id.lblListHeader_memo); lblListHeader_head.setText(Header_array[0]);
lblListHeader_memo.setText("1.1.0"+ "." + Header_array[1]); return convertView; } @Override public boolean hasStableIds() { return false; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } }
====================== fragment ======================
先宣告
ExpandableListAdapter listAdapter; ExpandableListView expListView; List<String> listDataHeader; HashMap<String, List<String>> listDataChild;
在這邊我們需要在adapter中加入每個版本及每個版本更新的內容
所以要在listDataHeader 與 listDataChild 中先塞入資料
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
viewRoot = inflater.inflate(R.layout.fragment_04, container, false);
expListView = (ExpandableListView) viewRoot.findViewById(R.id.lvExp);
expListView.setGroupIndicator(null);//預設的箭頭設為null(不使用),沒有設定null的話預設在左邊的箭頭會出現
prepareListData(); //這邊先做準備資料的動作
listAdapter = new ExpandableListAdapter(context, listDataHeader, listDataChild);
expListView.setAdapter(listAdapter);
return viewRoot;
}
private void prepareListData() {
listDataHeader = new ArrayList();
listDataChild = new HashMap>();
JSONObject jsonObject;
JSONArray array = null;
try {
jsonObject = new JSONObject(getVersionJson(context));
array = jsonObject.getJSONArray("versionList");
} catch (JSONException e) {
e.printStackTrace();
}
// 加入Head資料
listDataHeader.add("1.1.0"+",,,+"+"0003"); //",,,+" 沒有特別的意思,方便做split的動作(投機取巧的方式,建議少這樣用)
List ItemsList = new ArrayList();
StringBuilder sb = new StringBuilder();
// 加入每個item的資料
for (int i = 0; i <array.length(); i++) {
sb = new StringBuilder();
try {
JSONObject jsonObjectVersionList = array.getJSONObject(i);
String version = jsonObjectVersionList.getString("Version");
JSONArray array2 = jsonObjectVersionList.getJSONArray("memoList");
for (int j = 0; j < array2.length(); j++) {
JSONObject jsonObjectMemoList = array2.getJSONObject(j);
String memo = jsonObjectMemoList.getString("memo");
sb.append(memo);
}
ItemsList.add("1.1.0."+version+",,,+"+sb);
} catch (JSONException e) {
e.printStackTrace();
}
}
listDataChild.put(listDataHeader.get(0), ItemsList);
}
注意:
1 . 在這邊加入的版本資料是從一個json檔內的資料取出(改天寫一篇有關json的)
配合json做成範例的原因,因為在開發的過程中很常見到需要透過API拿回來Response的資料
蠻多都是用json的格式,我們需要解析後再取出需要的資訊來應用,所以這範例就用這種方式呈現。
2 . 在開發的過程中盡量別用"1.1.0"+",,,+"+"0003"類似的方式來加資料
在這是因為寫範例練習文章,先用簡單的方式呈現,但相信新手起步時很多人都會這樣做
因為很方便@@a.....當然方便的過程中後來我也是吃了閉門羹.....
有機會在寫一篇在開發用這種寫法的缺點在哪~


沒有留言:
張貼留言