轉載請標明出處:
http://www.cnblogs.com/dingxiansen/p/8194669.html
本文出自:丁先森-博客園
最近在項目中要使用ExpandableListView來實現一個下面這種效果

效果描述:這個要求的是點擊一個時展開點擊的哪一項,其余的都關閉(互斥效果),要實現點擊時切換字體的顏色。
還沒寫的時候在網上看了一下,什么資源都有,也不管能不能實現就貼代碼,要分下demo,但是充了幣下載下來,呵呵,不是自己要的那種效果。
下面的gif是我實現的效果(真實效果)

看完效果圖,開始說怎么實現的
數據源,這里我使用的是真實數據截取出來的json,首先先看一下
[{"id":117,"area_name":"昌平區","cinemas":[{"id":"1","cinema_name":"DMC昌平保利影劇院","cinema_address":"昌平區鼓樓南街佳蓮時代廣場4樓","area_id":"117","area_name":"昌平區","logo":"http:\/\/img.komovie.cn\/cinema\/14205106672446.jpg"},{"id":"2","cinema_name":"保利國際影城-龍旗廣場店","cinema_address":"昌平區黃平路19號院3號樓龍旗購物中心3樓","area_id":"117","area_name":"昌平區","logo":"http:\/\/img.komovie.cn\/cinema\/14203529883434.jpg"}]},{"id":109,"area_name":"朝陽區","cinemas":[{"id":"7","cinema_name":"北京劇院","cinema_address":"朝陽區安慧里三區10號","area_id":"109","area_name":"朝陽區","logo":"http:\/\/img.komovie.cn\/cinema\/14207675478321.jpg"},{"id":"8","cinema_name":"朝陽劇場","cinema_address":"朝陽區東三環北路36號","area_id":"109","area_name":"朝陽區","logo":"http:\/\/img.komovie.cn\/cinema\/14203512065410.jpg"},{"id":"10","cinema_name":"勁松電影院","cinema_address":"朝陽區勁松中街404號","area_id":"109","area_name":"朝陽區","logo":"http:\/\/img.komovie.cn\/cinema\/14213800192810.jpg"}]},{"id":110,"area_name":"豐台區","cinemas":[{"id":"67","cinema_name":"保利國際影城-大峽谷店","cinema_address":"豐台區南三環西路首地大峽谷購物中心5樓","area_id":"110","area_name":"豐台區","logo":"http:\/\/img.komovie.cn\/cinema\/14203575287090.jpg"},{"id":"68","cinema_name":"保利國際影城-萬源店","cinema_address":"豐台區東高地萬源北路航天萬源廣場5樓","area_id":"110","area_name":"豐台區","logo":"http:\/\/img.komovie.cn\/cinema\/14203530487616.jpg"},{"id":"69","cinema_name":"恆業國際影城-北京六里橋店","cinema_address":"北京市豐台區萬豐路68號銀座和諧廣場購物中心5層\t","area_id":"110","area_name":"豐台區","logo":""}]}]
數據格式是這樣的

地區對象中包含一個影院集合。
看完了數據格式,下面就來看代碼實現效果和問題
第一個效果:互斥效果,展開當前點擊的,關閉其他以前打開的
因為點擊的是Group,所以要想實現這個效果肯定就要在setOnGroupClickListener這個監聽中實現
代碼如下(這段代碼直接就可以使用):
private int lastClick = -1;//上一次點擊的group的position,定義在全局 // Group點擊事件,點擊一個Group隱藏其他的(只顯示一個) listview.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView expandableListView, View view, int i, long l) { if (lastClick == -1) { listview.expandGroup(i); } if (lastClick != -1 && lastClick != i) { listview.collapseGroup(lastClick); listview.expandGroup(i); } else if (lastClick == i) { if (listview.isGroupExpanded(i)) { listview.collapseGroup(i); } else if (!listview.isGroupExpanded(i)) { listview.expandGroup(i); } } lastClick = i; return true; } }); // 子項點擊事件 listview.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView expandableListView, View view, int parentPos, int childPos, long l) { /* Toast.makeText(ExpandableListViewTestActivity.this, dataset.get(parentList[parentPos]).get(childPos), Toast.LENGTH_SHORT).show();*/ Toast.makeText(getActivity(), datasets.get(PList[parentPos]).get(childPos).getCinema_name() + "影院Id:" + datasets.get(PList[parentPos]).get(childPos).getId() + "區域Id:" + datasets.get(PList[parentPos]).get(childPos).getArea_id(), Toast.LENGTH_SHORT).show(); return true; } }); }
第二個效果,自定義的布局,隱藏左邊原始的箭頭,右側顯示自己想要實現的箭頭或者圖片。
隱藏原始箭頭,要在布局中設置
android:groupIndicator="@null"
右側實現自己想要的圖片
在Parent布局中設置一個自己想要的圖片,不知道網上的其他答案為什么那么麻煩
evl_cinema_list_item_cityproper.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ffffff" android:orientation="horizontal"> <TextView android:id="@+id/parent_title" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_margin="10dp" android:layout_weight="3" android:drawablePadding="5dp" android:text="這是父item" android:textColor="@color/black" android:textSize="18sp" android:textStyle="bold" /> <!-- 這就是自己想要的那個圖片--> <ImageView android:id="@+id/parent_img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:layout_marginTop="10dp" android:layout_weight="0.5" android:src="@mipmap/star_grey" /> </LinearLayout>
相同字布局,也就是二級,你也可以自己定義自己想要的效果,代碼實現在Adapter中實現
選中時切換字體在getGroupView方法中,Boolean直接判斷,true選中,否則反之,右側圖片也和這個的實現思路一樣
代碼中都有注釋,應該都可以看懂
代碼如下:
MyExpandableListViewAdapter
/*適配器*/ private class MyExpandableListViewAdapter extends BaseExpandableListAdapter { // 獲得某個父項的某個子項 @Override public Object getChild(int parentPos, int childPos) { return datasets.get(PList[parentPos]).get(childPos); } // 獲得父項的數量 @Override public int getGroupCount() { if (datasets == null) { Toast.makeText(getActivity(), "dataset為空", Toast.LENGTH_SHORT).show(); return 0; } return datasets.size(); } // 獲得某個父項的子項數目 @Override public int getChildrenCount(int parentPos) { if (datasets.get(PList[parentPos]) == null) { Toast.makeText(getActivity(), "\" + parentList[parentPos] + \" + 數據為空", Toast.LENGTH_SHORT).show(); return 0; } return datasets.get(PList[parentPos]).size(); } // 獲得某個父項 @Override public Object getGroup(int parentPos) { return datasets.get(PList[parentPos]); } // 獲得某個父項的id @Override public long getGroupId(int parentPos) { return parentPos; } // 獲得某個父項的某個子項的id @Override public long getChildId(int parentPos, int childPos) { return childPos; } // 按函數的名字來理解應該是是否具有穩定的id,這個函數目前一直都是返回false,沒有去改動過 @Override public boolean hasStableIds() { return false; } // 獲得父項顯示的view @Override public View getGroupView(int parentPos, boolean b, View view, ViewGroup viewGroup) { if (view == null) { LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(elv_cinema_list_item_cityproper, null); } view.setTag(elv_cinema_list_item_cityproper, parentPos); view.setTag(R.layout.elv_cinema_list_item_cinema, -1); parentText = (TextView) view.findViewById(R.id.parent_title); ImageView parent_img = view.findViewById(R.id.parent_img); // 設置展開和收縮的文字顏色 if (b) { parentText.setTextColor(Color.parseColor("#2FD0B5")); parent_img.setImageResource(R.mipmap.star_yellow); } else { parentText.setTextColor(Color.BLACK); parent_img.setImageResource(R.mipmap.star_grey); } parentText.setText(PList[parentPos]); return view; } // 獲得子項顯示的view @Override public View getChildView(final int parentPos, final int childPos, boolean b, View view, ViewGroup viewGroup) { if (view == null) { LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.elv_cinema_list_item_cinema, null); } view.setTag(elv_cinema_list_item_cityproper, parentPos); view.setTag(R.layout.elv_cinema_list_item_cinema, childPos); TextView text = (TextView) view.findViewById(R.id.child_title); TextView textView = view.findViewById(R.id.child_message); text.setText(datasets.get(PList[parentPos]).get(childPos).getCinema_name()); textView.setText(datasets.get(PList[parentPos]).get(childPos).getCinema_address()); return view; } // 子項是否可選中,如果需要設置子項的點擊事件,需要返回true @Override public boolean isChildSelectable(int i, int i1) { return true; } }
這里的adapter我也沒有新建一個類存放,你們也可以分離出來,我這個是放在了類中
代碼我放到了雲盤里,GitHub也好久沒往上提交了。就先用這個吧
源碼地址:https://pan.baidu.com/s/1kVmZnvT 密碼:xu1x
如果鏈接失效或者其他問題請發送到我的郵箱 dingchao7323@qq.com
感謝您百忙之后查看到我的博客,如果能解決您的問題,我的榮幸,共同學習,共同進步。
