最近项目需要用到类似qq的分组功能,网上找了一下是用ExpandableListView或者自定义或者Recycleview来实现的,这里我使用的是ExpandableListView,遇到的问题记录如下:
1、ExpandableListView 展开失败的可能原因(ExpandableListView的group里添加button后不能展开的解决方法)
我们就在 getGroupView 函数中返回这个view,注意:里面 R.layout.布局 就是我们的自定义一级目录 xml 布局
文件,也是我要说的坑所在。
我在确定编码没问题之后,就点运行了,几秒后, getGroupView 加载的一级目录 xml 布局显示出来了,OK,很好,然后我就点击了,点了之后发现,妹的,没展开二级目录。然后就屁颠屁颠地回去找bug,代码确定没错,于是加入了很多log,再次运行,查看日志。我勒个去!
@Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent)
这货居然没被执行,里面的log 没打印出。于是下意识地去查看我在getChildView引入的 xml 布局,我上面说的第一个 xml 布局是一级目录的,在getChildView 是二级目录的 布局。查看之后,实在找不出它有错的理由,于是乎,就找之前成功过的例子 xml 文件替换进去,运行,点击,还是不行,当时我就fuck 了 dog 了。
然后转至 getGroupView 一级目录 xml布局的引入函数,查看仍找不出错的理由,同上,用之前成功过的替换下,运行,点击,made,居然行了。然后我就开始 把原来不行的 布局文件 和 替换后可以的来对比。
控件类型对比差异:不行的布局文件带有 button 控件,可以的没有带有button,其它地方一样。
看到这,突然觉得,是不是 button 的点击属性覆盖了原本的一级目录可点击属性?再看看 button 的宽和高,即它的有效点击范围,都是 wrap,按道理没占满整个父view,我点其他地方,不就是没点到它吗。可事实就是如此。button 的存在导致 ExpandableListView 一级目录可点击性失效。这真是天坑,马上百度百度,看看有没有相同案例,百度了才发现,有碰到和我相同问题的,但是都没有解决!!!心情有点小激动,哈哈。
解决方案一:
ExpandableListView 的 数据适配器 ExpandableListAdapter 中的 getGroupView 函数中所引入的自定义一级目录 xml 布局文件不能带有 button,否则会导致展开失效,ImageButton没尝试过,不过可能也是不行的。
解决方案二:
ExpandableListView的group里添加button后不能展开的原因是button获取了原本属于group的焦点,所以不能展开
知道原因,解决起来就简单了:设置button, reply.setFocusable(false); 设置button不获取焦点,但可以点击reply.setClickable(true); 如此一来就ok啦
2、首次加载全部展开
mExpandableListView.setAdapter(mExpandableListViewAdapter); for (int i = 0; i < mDataGroup.size(); i++) { mExpandableListView.expandGroup(i); }
提醒:加载前别忘了判断adapter是否为空和有没有Group数据哦
3、不能点击收缩
mExpandableListView.setOnGroupClickListener(new OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { return true; } });
把ExpandableListView的组点击事件屏蔽
4、ExpandableListView的长按事件
//长按事件 mExpandableListView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() { @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { menu.setHeaderTitle("选择操作"); menu.add(0, DOWNLOAD_RETRY, 0, "重试"); menu.add(0, DOWNLOAD_DEL, 0, "删除"); menu.add(0, DOWNLOAD_START, 0, "启动"); } });
/** * 长按菜单响应函数 */ @Override public boolean onContextItemSelected(MenuItem item) { //关键代码 ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) item.getMenuInfo(); int type = ExpandableListView.getPackedPositionType(info.packedPosition); if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) { //上面的type设定这里类型的判定!这里是child判定! int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition); //在child判定里面,获取该child所属group! int childPos = ExpandableListView.getPackedPositionChild(info.packedPosition); //在child判定里面,获取该child所属position! switch (item.getItemId()) { case DOWNLOAD_RETRY: makeTextShort("我是重试"); break; case DOWNLOAD_DEL: makeTextShort("我是删除"); break; case DOWNLOAD_START: makeTextShort("我是启动"); default: break; } return true; } return false; }
5、去掉 ExpandableListView Group 上的箭头
可以 在xml 布局中设置
android:groupIndicator="@null"
也可以在Java代码中设置
mExpandableListView.setGroupIndicator(null);
6、设置ExpandableListView 默认是展开的
exListView.setAdapter(exlvAdapter); //遍历所有group,将所有项设置成默认展开 intgroupCount = exListView.getCount(); for (inti=0; i<groupCount; i++) { exListView.expandGroup(i); };
注:先实例化exListView (ExpandableListView所有数据齐全后可用,否则报错)
7、自定义ExpandableListView 的箭头
首先,自定义一个expandablelistviewselector.xml文件,具体内容如下:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_expanded="true" android:drawable="@drawable/expandablelistviewindicatordown" /> <item android:drawable="@drawable/expandablelistviewindicator" /> </selector>
Java代码如下:
settingLists.setGroupIndicator(this.getResources().getDrawable(R.layout.expandablelistviewselector));
或者
android:groupIndicator="@drawable/groupIndicator_selector"
8、将默认的箭头修改到右边显示
1)首先ExpandableListViewelistview;
elistview.setGroupIndicator(null);//将控件默认的左边箭头去掉
2)在自定义的继承自BaseExpandableListAdapter的adapter中有一个方法
/** * 父类view */ @Override public View getGroupView(intgroupPosition, booleanisExpanded, View convertView, ViewGroup parent) { Log.i("zhaoxiong","parent view"); LinearLayoutparentLayout=(LinearLayout) View.inflate(context, R.layout.wowocoupons_parent_item, null); TextViewparentTextView=(TextView)parentLayout.findViewById(R.id.parentitem); parentTextView.setText(parentlist.get(groupPosition)); ImageViewparentImageViw=(ImageView) parentLayout.findViewById(R.id.arrow); //判断isExpanded就可以控制是按下还是关闭,同时更换图片 if(isExpanded){ parentImageViw.setBackgroundResource(R.drawable.arrow_down); }else{ parentImageViw.setBackgroundResource(R.drawable.arrow_up); } return parentLayout; }
9、ExpandableListView中包含多个group,想要展开一个group时,其他group都关闭
exList.setOnGroupExpandListener(new OnGroupExpandListener() { @Override public void onGroupExpand(int groupPosition) { for (int i = 0; i < getData().size(); i++) { if (groupPosition != i) { exList.collapseGroup(i); } } } });
10、expandablelistview的Group点击事件,onGroupClick的返回值false展开,true不展开(如果配合默认展开,就会固定展开不收缩)
tt_list.setOnGroupClickListener(new OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { IsFlag=true; if(adapter.getGroupData().get(groupPosition).getList().size()==1){ Bundle b=new Bundle(); b.putInt("saveIndex", 0); // b.putString("mac", mac); // b.putString("deviceId", mDeviceId); b.putSerializable("datalist", adapter.getGroupData().get(groupPosition).getList()); Intent i=new Intent(WappushBindingActivity.this,VideoPlayerActivity.class); i.putExtras(b); startActivity(i); } // int groupCount = tt_list.getCount(); // for (int i=0; i<groupCount; i++){ // if(i!=GroupPosition) // tt_list.collapseGroup(i); // }; // Log.v("xulongheng*WappushBind*tt_list", "onGroupClick:"+previousX+"/"+previousY); return true; //默认为false,设为true时,点击事件不会展开Group } });