服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - 支持多项选择的ExpandableListView

支持多项选择的ExpandableListView

2022-03-03 14:55swingseagull Android

这篇文章主要为大家详细介绍了支持多项选择的ExpandableListView,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了ExpandableListView多项选择展示的具体代码,供大家参考,具体内容如下

目标(需求):

1. 创建一个可展开可收缩的列表;

2. 其列表项包含多个checkable的部件,当选择某一行时,该行包含的checkable的部件需要作出相应的变化;

3. 可以选择多个列表项,并且这些列表项可被读出

结果图:

支持多项选择的ExpandableListView

实现:

1. 创建主layout用于规划列表显示。对于具体的列表项,为了实现的方便我们也创建一个layout文件。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="utf-8"?>
<com.home.mymultichecklistview.CheckableLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/layout"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="horizontal" >
 <com.home.mymultichecklistview.CheckableTextView
   android:id="@+id/item"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_marginTop="6dip"
   style="@style/text"
   android:layout_weight="1"
 />
   
 <com.home.mymultichecklistview.InertCheckBox
   android:id="@+id/checkbox"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_marginRight="5dp"
   android:maxWidth="40dp"
   android:maxHeight="40dp"
   android:focusable="false"
   android:layout_gravity="right"
   android:button="@drawable/checkbox"
 /> 
 
  
</com.home.mymultichecklistview.CheckableLinearLayout>

2. 类似ListView,ExpandableListView也是通过Adapter来管理其包含的各种元素和操作,这里我们创建一个扩展自BaseExpandableListAdapter的Adapter。与ListView不同的是,ExpandableListAdapter要渲染实现两级View(Group级和列表项级)的操作。它通过getGroupView()渲染Group项,通过getChildView()渲染列表子项。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@Override
  public View getGroupView(int groupPosition, boolean isExpanded,
      View convertView, ViewGroup parent) {
    View groupView = convertView;
    if (groupView == null) {
      groupView = new TextView(context);
      ((TextView)groupView).setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
      groupView.setPadding(50,0,0,0);
    }
    ((TextView)groupView).setText(groupData[groupPosition]);
    ((TextView)groupView).setTextColor(context.getResources().getColor(R.color.fgcolor));
     
    return groupView;
  }
 
  @Override
  public View getChildView(final int groupPosition, final int childPosition,
      boolean isLastChild, View convertView, ViewGroup parent) {
    View itemView = convertView;
    final ViewHolder vh;
    if (itemView == null) {
      LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      itemView = inflater.inflate(R.layout.item_view, null);
       
      vh = new ViewHolder();
      vh.layout = (CheckableLinearLayout)itemView.findViewById(R.id.layout);
      vh.item = (TextView)itemView.findViewById(R.id.item);
      itemView.setTag(vh);
    } else {
      vh = (ViewHolder)itemView.getTag();
    }
    vh.item.setText(itemData[groupPosition][childPosition]);
    final ExpandableListView listView = ((ExpandableListView)((MainActivity)context).findViewById(R.id.list));
    final int position = listView.getFlatListPosition(ExpandableListView.getPackedPositionForChild(groupPosition, childPosition));
    listView.setItemChecked(position, checkedState[groupPosition][childPosition]);
    vh.layout.setOnClickListener(new OnClickListener() {
 
      @Override
      public void onClick(View v) {
        ((CheckableLinearLayout)v).toggle();
        checkedState[groupPosition][childPosition] = !checkedState[groupPosition][childPosition]; 
        listView.setItemChecked(position, ((CheckableLinearLayout)v).isChecked());
      }
    });
    return itemView;
  

3. 为每一列表子项容器创建OnClickListener监听鼠标的点击事件。在这里要注意,由于列表子项包含了CheckBox,所以为了使点击事件不要被CheckBox捕获,我们需要创建一个扩展自CheckBox的类来屏蔽鼠标和键盘事件。同时,需要在这个容器里搜索其包含的checkable的部件并将check操作传给这些部件。

Adapter中的方法getChildView()需要实现鼠标点击监听器:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public View getChildView(final int groupPosition, final int childPosition,
      boolean isLastChild, View convertView, ViewGroup parent) {
  View itemView = convertView;
  final ViewHolder vh;
...
 
    final int position = listView.getFlatListPosition(ExpandableListView.getPackedPositionForChild(groupPosition, childPosition));
    listView.setItemChecked(position, checkedState[groupPosition][childPosition]);
  vh.layout.setOnClickListener(new OnClickListener() {
 
  @Override
  public void onClick(View v) {
    ((CheckableLinearLayout)v).toggle();
    checkedState[groupPosition][childPosition] = !checkedState[groupPosition][childPosition]; 
     listView.setItemChecked(position, ((CheckableLinearLayout)v).isChecked());
  }
 });
 return itemView;
}

扩展自CheckBox的InertCheckBox需要屏蔽键盘和鼠标事件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class InertCheckBox extends CheckBox {
  @Override
  public boolean onKeyDown(int keyCode, KeyEvent event) {
  //直接返回false
  return false;
  }
 
  @Override
  public boolean onKeyUp(int keyCode, KeyEvent event) {
  //直接返回false
  return false;
}
 
  @Override
  public boolean onTouchEvent(MotionEvent event) {
  //直接返回false
  return false;
  }
 
   @Override
   public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
  //直接返回false
  return false;
  ...
}

列表项容器需要实现Checkable接口并且把check操作传递给其checkable的子部件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class CheckableLinearLayout extends LinearLayout implements Checkable {
...
  @Override
  public void setChecked(boolean checked) {
  this.isChecked = checked;
  for (Checkable view : checkableViews) {
   view.setChecked(checked);
   }
  }
   
  @Override
  public boolean isChecked() {
   return this.isChecked;
  }
 
  @Override
  public void toggle() {
   isChecked = !isChecked;
   for (Checkable view : checkableViews)    {
  view.toggle();
   }
  }
 
  @Override
  protected void onFinishInflate() {
  super.onFinishInflate();
     
    for (int i=0; i<this.getChildCount(); i++) {
  findCheckableChild(this.getChildAt(i));
  }
 }
 
  private void findCheckableChild(View child) {
  if (child instanceof Checkable) {
    checkableViews.add((Checkable)child);
  }
     
  if (child instanceof ViewGroup) {
      for (int i=0; i<((ViewGroup)child).getChildCount(); i++) {
    findCheckableChild(((ViewGroup) child).getChildAt(i));
    }
  }
  }
...
}

开发中遇到的问题:

1. 渲染后的child view类似于放在一个cache中,下一次再通过convertView取时,由于Group的收缩或扩展操作会隐藏/显示一些child view,导致某一child View的flat position发生变化,获取到的convertView不是原来希望获取的view。所以,每次获取到view后都需要对其内容重新设置(比如设置正确文本,设置监听器等)

2. check的状态设置很tricky。我开始认为直接在监听器中调用容器的toggle()方法即可。结果发现一旦某个group做了expand或collapse操作后,所有列表项的check状态全没了。后来发现原来group做了expand/collapse操作后,ListView会对其所有子项重新设置check状态,而check状态的值是存在ListView的一个SparseBooleanArray表里(mCheckStates)。由于没有对这个表进行设置,所以一刷新check状态就全丢了。并且由于这个表的key是基于拉平后所有可见的列表项的位置定的,当group扩展或收缩后,同一个列表项,它拉平后的位置还会变化。所以,为了解决这个问题,我在adapter里增加了一个二维表用于记录每一列表项的check状态。在执行 listView的setItemChecked函数时,其check状态是从这个自己创建的表中读出的,不能通过ListView的mCheckStates来读。这个我认为是ExpandableListView的一个缺陷。

遗留的已知问题:

我使用了@drawable/checkbox 来定义checkbox check 和uncheck时的图片,但当checkbox被check上时,这个checked的图片没有生效。不知道为什么,还需要进一步debug.

源程序:Multi-check-in-expandablelistview

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/swingseagull/article/details/17462405

延伸 · 阅读

精彩推荐
  • AndroidAndroid中AsyncTask详细介绍

    Android中AsyncTask详细介绍

    这篇文章主要介绍了Android中AsyncTask详细介绍,AsyncTask是一个很常用的API,尤其异步处理数据并将数据应用到视图的操作场合,需要的朋友可以参考下...

    Android开发网7452021-03-11
  • AndroidAndroid CardView+ViewPager实现ViewPager翻页动画的方法

    Android CardView+ViewPager实现ViewPager翻页动画的方法

    本篇文章主要介绍了Android CardView+ViewPager实现ViewPager翻页动画的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    Abby代黎明9602022-03-02
  • AndroidAndroid实现Service获取当前位置(GPS+基站)的方法

    Android实现Service获取当前位置(GPS+基站)的方法

    这篇文章主要介绍了Android实现Service获取当前位置(GPS+基站)的方法,较为详细的分析了Service基于GPS位置的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    Ruthless8342021-03-31
  • AndroidAndroid编程解析XML方法详解(SAX,DOM与PULL)

    Android编程解析XML方法详解(SAX,DOM与PULL)

    这篇文章主要介绍了Android编程解析XML方法,结合实例形式详细分析了Android解析XML文件的常用方法与相关实现技巧,需要的朋友可以参考下...

    liuhe68810052021-05-03
  • AndroidAndroid实现固定屏幕显示的方法

    Android实现固定屏幕显示的方法

    这篇文章主要介绍了Android实现固定屏幕显示的方法,实例分析了Android屏幕固定显示所涉及的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    鉴客6192021-03-27
  • Android汇总Android视频录制中常见问题

    汇总Android视频录制中常见问题

    这篇文章主要汇总了Android视频录制中常见问题,帮助大家更好地解决Android视频录制中常见的问题,需要的朋友可以参考下...

    yh_thu5192021-04-28
  • AndroidAndroid程序设计之AIDL实例详解

    Android程序设计之AIDL实例详解

    这篇文章主要介绍了Android程序设计的AIDL,以一个完整实例的形式较为详细的讲述了AIDL的原理及实现方法,需要的朋友可以参考下...

    Android开发网4642021-03-09
  • AndroidAndroid界面效果UI开发资料汇总(附资料包)

    Android界面效果UI开发资料汇总(附资料包)

    android ui界面设计,友好的界面会提高用户体验度;同时也增强了android ui界面设计的难度,本文提供了一些常用开发资料(有下载哦)感兴趣的朋友可以了解下...

    Android开发网4672021-01-03