ExpandableListView的使用和理解
来源:互联网 发布:网络无法登陆暴雪 编辑:程序博客网 时间:2024/06/06 09:58
ExpandableListView顾英文思意:可扩展列表视图。
之前一直看别人用这个控件,哇,觉得肯定很复杂,数据也很复杂吧,也就一直没尝试用到这个控件,就和我对自定义View是一样的感觉,是新手必经之路,又很怕去触碰,觉得比较难,放在以后再说,但是,建议,没有什么难不难,去理解,去写控件的代码,走一遍,想想,就理解了。言归正传:
ExpandableListView 就是ListView的进化版,满足了一般ListView做不到的事情,如现在的QQ好友列表的样式,点击拉伸扩展,再点击缩小,着就是父item和子item的关系了。
首先,先看看主布局:activity_main.xml:
<ExpandableListView android:id="@+id/expanda_list" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="#000000" />
仅此而已,外层你可以用LinearLayout也好,或者是最新的ConstraintLayout布局(约束布局)也好等等,都可以。
其次要需要创建两个xml布局,一个是父Item,一个是子Item,所有的只需要这两个布局去实现,因为我们有Holder呀,一个这么神奇复用的东西对吧~
父布局.xml:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="70dp" android:orientation="horizontal"> <RelativeLayout android:layout_width="match_parent" android:layout_height="70dp"> <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="20dp" /> <TextView android:id="@+id/txt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_toRightOf="@+id/img" android:text="张三" android:textSize="18sp" /> <TextView android:id="@+id/txt2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="20dp" android:gravity="right" android:text="4/17" /> </RelativeLayout></LinearLayout>
子布局xml:.
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="70dp" android:padding="3dp" android:orientation="horizontal"> <ImageView android:id="@+id/img" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginLeft="20dp" android:src="@drawable/ic_launcher" /> <LinearLayout android:layout_width="match_parent" android:layout_height="70dp" android:gravity="center_vertical" android:orientation="vertical"> <TextView android:id="@+id/txt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="皮皮护法" /> <TextView android:id="@+id/txt2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="哇,皮皮虾,我们走我们走" /> </LinearLayout></LinearLayout>
不要觉得看起来很多,这只是为了效果,其实很多都是没有意义的属性,比如有几个textview就不会用到他,只是让他显示text而已。
一般默认的ExpandableListView的父Item都是有小箭头的,可以理解为打开与不打开有个小三角形的指示图标。
在MainActivity.java中,类似的与ListView一样,需要放入数据,需要声明这个ExpandableListView控件,还需要一个适配器,以及两个复用的Holder就足够了。
我的代码有点乱,但是记住两个核心:
1. 一个List group = new ArrayList<>();这样的List是专门为父Item提供的,需要什么样的栏目,直接将数据放进该List即可。
2. 一个List《List《String》》 item_list =new ArrayList<>();这样的
List《List《String》> 是存放每个子Item相对应的数据,可以知道,item_list存放进去的是一个list<>对象,而在list对象中在放入相对应的String的数据,这个层级关系一定要理清楚。
下面是代码:
public class MainActivity extends AppCompatActivity { private ExpandableListView expandableListView; //expandablelistview控件 private MyExpandableListViewAdapter adapter; //适配器 private List<String> group_list = new ArrayList<>();//父item 显示的东西,加数据就多现实一栏父item 父列表 private List<String> text = new ArrayList<>(); //子item对应的文字集合 private List<Integer> tupian = new ArrayList<>(); //子item对应的图片集合 private List<List<String>> item_list = new ArrayList<>();//将子item放进来,适配进每个父Item的相对应子item private List<List<Integer>> item_list2 = new ArrayList<>();//将子item图片放进来,适配进每个父item相对应的子item @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /** * 父item的栏目,多一行则多显示一行的界面数据 */ group_list.add("我的好友"); group_list.add("我的亲人"); group_list.add("我的同学"); group_list.add("我的兄弟"); /** * 关于子item的数量,文字显示 */ text.add("皮皮虾"); text.add("石乐志"); text.add("真皮"); text.add("石乐志"); text.add("真皮"); text.add("石乐志"); /** * 这一栏负责子item的图片显示, 所有的东西都是同步,改变12行,每个子item 1.2行都会变 */ tupian.add(R.drawable.two); tupian.add(R.drawable.two); tupian.add(R.drawable.two); tupian.add(R.drawable.two); tupian.add(R.drawable.two); tupian.add(R.drawable.two); item_list2.add(tupian); item_list2.add(tupian); item_list2.add(tupian); item_list2.add(tupian); item_list2.add(tupian); item_list2.add(tupian); /** * 子Item的文字。和图片必须同时增加,不然就会指数越界,切记。两个同时从4行加到6行才行 */ /** * 决定着多少个父item能被打开,加入有四个父item,但是只写三行下面的代码,。第四个父item就会指数越界 */ item_list.add(text); item_list.add(text); item_list.add(text); item_list.add(text); expandableListView = (ExpandableListView) findViewById(R.id.expanda_list);//找该控件 expandableListView.setGroupIndicator(null); /** * 可用lambda表达式简化,一般是需要写出来的,用lambda可省略 * 对父子item的点击操作都可以写在这里面的逻辑中 */ expandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView expandableListView, View view, int i, long l) { if (item_list.get(i).isEmpty()) { return true; } return false; } }); expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView expandableListView, View view, int i, int i1, long l) { Toast.makeText(MainActivity.this, "group=" + i + "child=" + i1, Toast.LENGTH_SHORT).show(); return false; } }); adapter = new MyExpandableListViewAdapter(this); expandableListView.setAdapter(adapter); } private class MyExpandableListViewAdapter extends BaseExpandableListAdapter { private Context mContext; public MyExpandableListViewAdapter(Context context) { this.mContext = context; } @Override public int getGroupCount() { return group_list.size(); } @Override public int getChildrenCount(int i) { return item_list.get(i).size(); } @Override public Object getGroup(int i) { return group_list.get(i); } @Override public Object getChild(int i, int i1) { return item_list.get(i).get(i1); } @Override public long getGroupId(int i) { return i; } @Override public long getChildId(int i, int i1) { return i1; } @Override public boolean hasStableIds() { return true; } /** *获得父布局的逻辑操作 */ @Override public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) { GroupHolder groupHolder = null; if (view == null) { view = LayoutInflater.from(mContext).inflate(R.layout.expendlist_group, null); groupHolder = new GroupHolder(); groupHolder.txt = (TextView) view.findViewById(R.id.txt); groupHolder.img = (ImageView) view.findViewById(R.id.img); view.setTag(groupHolder); } else { groupHolder = (GroupHolder) view.getTag(); } /** * 在这里 !b表示没有被父item没有被点击。前面的横向指针图片不会变 * 如果被点击,则进入else逻辑,更换指针向下的图片 */ /* if (!b) { groupHolder.img.setBackgroundResource(R.drawable.two); } else { groupHolder.img.setBackgroundResource(R.drawable.ic_launcher); }*/ groupHolder.txt.setText(group_list.get(i)); return view; } /** * 获得子布局的逻辑 */ @Override public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) { ItemHolder itemHolder = null; if (view == null) { view = LayoutInflater.from(mContext).inflate(R.layout.expendlist_item, null); itemHolder = new ItemHolder(); itemHolder.txt = (TextView) view.findViewById(R.id.txt); itemHolder.img = (ImageView) view.findViewById(R.id.img); view.setTag(itemHolder); } else { itemHolder = (ItemHolder) view.getTag(); } itemHolder.txt.setText(item_list.get(i).get(i1)); itemHolder.img.setBackgroundResource(item_list2.get(i).get(i1)); return view; } @Override public boolean isChildSelectable(int i, int i1) { return true; } } private class GroupHolder { TextView txt; ImageView img; } private class ItemHolder { TextView txt; ImageView img; }}
接下来是效果图:
我相信,代码的注释也都很清楚了,当然,不要忘记最后两个Holder,一个是对应获得父View的Holder,一个是对应子View的Holder,有所区别。剩下主要的也就是adapter的代码,无须担心,继承了BaseExpandableListAdapter之后AS会提示让你倒入这些方法,再去写就可以了。
对于上面的增加数据,我是把它写死了,那么就要注意,当增加一个子item的Text的时候,一定要增加一个相对应的子Image,因为text 和 image在我的布局是相对应一起的,如果只加一个而不管增加相对应的一个text或者image的话,就会数组越界异常,导致程序崩溃。
如果你能看到这里,我们就继续解释一下数据,上面的代码是将数据写死,如果需要时事获得数据呢?也很简单,通过从服务器获得的数据,将父item数据放入List<>中,将子Item的数据,依次add放入List<>中,在将该List<> 再次add进add进List《List》就可以了。其他的适配过程都一样。
当然,还有一种思路,这样的ExpandableListView看起来,是不是就和LinearLayout相似,是的,这样就接触到了自定义View有关的知识,自己写个Layout继承LinearLayout,然后抓取父Item 子Item的布局,通过View view = LayoutInflater.from(context).inflate(R.layout.child_layout)来抓取布局,然后自定义Layout.addView(view)是不是就行了呢。
这是粗略的一个自定义模拟ExpandableListView,可以直接从as 的 open打开,具体有想法的可以去琢磨琢磨改一改,还是挺有意思的。
http://download.csdn.net/detail/chenxuanhe1995/9787506
- ExpandableListView的使用和理解
- ExpandableListView 和SimpleExpandableListAdpater的使用
- ExpandableListView的使用和扩展
- ExpandableListView的使用
- ExpandableListView的使用
- Android ExpandableListView的使用
- Android ExpandableListView的使用
- 转载:ExpandableListView的使用
- ExpandableListView的使用
- expandablelistview的使用
- Android ExpandableListView的使用
- ExpandableListView组件的使用
- ExpandableListView的基本使用
- ExpandableListView的使用
- ExpandableListView的使用示例
- ExpandableListView的使用
- ExpandableListView的使用总结
- Android ExpandableListView的使用
- JavaScript小项目——2048数字游戏
- 下面说说unset的用处,与为什么
- 打印沙漏
- ajax 上传文件
- 图解Android View的scrollTo(),scrollBy()
- ExpandableListView的使用和理解
- cordova之hooks
- git基本操作二
- ContentProvider的启动流程分析
- 架构和分布式____安装和使用memcached
- 第76篇 一对多之稳定性研究及windows下部署官网音频最新到本地及array_uintersect_assoc 周五
- opencv最小二乘拟合平面
- 转载---JS页面跳转方法
- vue初探--路由简单使用