Android之路

导航

ExpandableListView简单使用

    Android 中关于ExpandableListView的简单使用,以一个demo为例,比较简单,主要用于理解一些概念性的知识。仅作为学习笔记。

1、定义:可扩展的ListView。

public class ExpandableListView extends ListView {
    ......
}

继承自ListView,因此基本使用方法同ListView:
(1)需要自定义一个继承自BaseExpandableListAdapter的Adapter;当然包括相关的布局等。
(2)注册监听事件;

由于该例子很简单,直接查看代码及注释,更清晰的显示常用方法的作用,在此不再详述。

2、基本用法:

//主界面布局:
    <Button
        android:id="@+id/expandBtn"
        android:textSize="18sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/expandable_des" 
        />
    
    <ExpandableListView 
        android:layout_marginTop="10dp"
        android:id="@+id/expandableListView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/bg_default" 
        android:groupIndicator="@null"
        android:visibility="gone"
         
        ></ExpandableListView>
    <!-- 
    android:groupIndicator="@null"  去掉系统自带的展开图标
     -->
  1 //自定义适配器ExpandAdapter.java
  2 public class ExpandAdapter extends BaseExpandableListAdapter {
  3     private final String TAG = "ExpandAdapter";
  4 
  5     private Context mContext;
  6     private LayoutInflater layoutInflater;
  7 
  8     private String[] groupNames = new String[]
  9             {"C++","JAVA","Android","HTML"};
 10 
 11 //    private Drawable leftDrawable;        //具体看本文末尾补充部分
 12     private int arrowUpId,arrowDownId;
 13 
 14     public ExpandAdapter(Context context) {
 15         // TODO Auto-generated constructor stub
 16         mContext = context;
 17         layoutInflater = LayoutInflater.from(mContext);
 18 
 19         arrowUpId = R.drawable.arrow_up;
 20         arrowDownId = R.drawable.arrow_down;
 21         
 22 //        leftDrawable = context.getDrawable(R.drawable.ic_launcher);
 23 //        leftDrawable.setBounds(0, 0, leftDrawable.getMinimumWidth(), leftDrawable.getMinimumHeight());
 24     }
 25 
 26     @Override
 27     public Object getChild(int arg0, int arg1) {
 28         // TODO Auto-generated method stub
 29         return null;
 30     }
 31 
 32     @Override
 33     public long getChildId(int arg0, int arg1) {
 34         // TODO Auto-generated method stub
 35         return arg1;
 36     }
 37 
 38     @Override
 39     public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View childView,
 40             ViewGroup parent) {   //子项布局
 41         // TODO Auto-generated method stub
 42         ChildHolder childHolder;
 43 
 44         if(childView == null){
 45             childView = layoutInflater.inflate(R.layout.child_view, null);
 46             childHolder = new ChildHolder();
 47             childHolder.child_content = (TextView) childView.findViewById(R.id.child_content);
 48             childView.setTag(childHolder);
 49         }else{
 50             childHolder = (ChildHolder) childView.getTag();
 51         }
 52 
 53 //        Log.d(TAG, "getChildView groupPos: " + groupPosition + "  childPos: " + childPosition);
 54 
 55 //        if(groupPosition < groupNames.length){
 56 //            groupHolder.name_type.setText(groupNames[groupPosition]);
 57 //        }
 58         
 59 //        if(childPosition % 2 == 0){
 60 //            childHolder.child_content.setText("使用  drawableLeft getChildView  getChildView  getChildView getChildView");
 61 //            childHolder.child_content.setCompoundDrawables(leftDrawable, null, null, null);
 62 //        }    
 63 
 64         return childView;
 65     }
 66 
 67     @Override
 68     public int getChildrenCount(int arg0) {  //子项总数
 69         return 5;
 70     }
 71 
 72     @Override
 73     public Object getGroup(int arg0) {
 74         return groupNames[arg0];
 75     }
 76 
 77     @Override
 78     public int getGroupCount() {    //一级列表项数
 79         return groupNames.length;
 80     }
 81 
 82     @Override
 83     public long getGroupId(int groupPosition) {
 84         return groupPosition;
 85     }
 86 
 87     @Override
 88     public View getGroupView(int groupPosition, boolean isExpand, View convertView, ViewGroup parent) {//一级列表项
 89         // TODO Auto-generated method stub
 90         GroupHolder groupHolder;
 91 
 92         if(convertView == null){
 93             convertView = layoutInflater.inflate(R.layout.grounp_view, null);
 94             groupHolder = new GroupHolder();
 95             groupHolder.img_type = (ImageView) convertView.findViewById(R.id.img_type);
 96             groupHolder.name_type = (TextView) convertView.findViewById(R.id.name_type);
 97             groupHolder.img_arrow = (ImageView) convertView.findViewById(R.id.img_arrow);
 98             convertView.setTag(groupHolder);
 99         }else{
100             groupHolder = (GroupHolder) convertView.getTag();
101         }
102 
103         if(isExpand){
104 //            groupHolder.img_arrow.setImageResource(R.drawable.arrow_up);
105             groupHolder.img_arrow.setImageResource(arrowUpId);
106         }else{
107 //            groupHolder.img_arrow.setImageResource(R.drawable.arrow_down);
108             groupHolder.img_arrow.setImageResource(arrowDownId);
109         }
110         
111         Log.i(TAG, "getGroupView groupPosition: " + groupPosition + "  isExpand: " + isExpand);
112 
113         if(groupPosition < groupNames.length){
114             groupHolder.name_type.setText(groupNames[groupPosition]);
115         }
116 
117         return convertView;
118     }
119 
120     @Override
121     public boolean hasStableIds() {
122         return false;
123     }
124 
125     //为了使子项响应点击事件,此处必须返回true!!!!!!!!!!!!!!!!!!!!!!!!!!!
126     @Override
127     public boolean isChildSelectable(int arg0, int arg1) {
128         // TODO Auto-generated method stub
129         return true;
130     }
131 
132     class GroupHolder{
133         ImageView img_type,img_arrow;
134         TextView name_type;
135     }
136     class ChildHolder{
137         TextView child_content;
138     }
139 
140 }
 1 ExpandableListViewActivity中的基本使用:
 2 
 3      expandableListView = (ExpandableListView) findViewById(R.id.expandableListView);
 4 
 5         expandAdapter = new ExpandAdapter(this);
 6         expandableListView.setAdapter(expandAdapter);
 7 
 8 //注册监听事件:
 9     private void initExpandableListener(){
10         expandableListView.setOnGroupClickListener(new OnGroupClickListener() {
11             @Override
12             public boolean onGroupClick(ExpandableListView expandableListView, View arg1, int groupPosition,
13                     long arg3) {                    //组(一级列表)点击事件       默认return false;若设为true,表示点击列表不会展开
14                 // TODO Auto-generated method stub
15                 Log.i(TAG, "onGroupClick " + groupPosition);
16 
17                 return false;
18             }
19         });
20         expandableListView.setOnGroupCollapseListener(new OnGroupCollapseListener() {
21             @Override
22             public void onGroupCollapse(int groupPosition) {        //折叠
23                 // TODO Auto-generated method stub
24                 Log.i(TAG, "onGroupCollapse " + groupPosition);
25 
26             }
27         });
28         expandableListView.setOnGroupExpandListener(new OnGroupExpandListener() {
29             @Override
30             public void onGroupExpand(int groupPosition) {            //展开    若需要展开某项,其他项关闭,可在该处理方法中写入相应逻辑
31                 // TODO Auto-generated method stub
32                 Log.i(TAG, "onGroupExpand " + groupPosition);
33 
34             }
35         });
36 
37 
38         //Child
39         expandableListView.setOnChildClickListener(new OnChildClickListener() {
40 
41             @Override
42             public boolean onChildClick(ExpandableListView arg0, View arg1, int groupPosition,
43                     int childPosition, long arg4) {
44                 // TODO Auto-generated method stub
45                 Log.i(TAG, "onChildClick " + groupPosition  + "  " + childPosition);
46 
47                 return false;
48             }
49         });
50 
51 
52         //添加一个按钮,用于测试expandGroup(int groupPos, boolean animate)中的animate不同值的显示效果.
53         Button expandBtn = (Button) findViewById(R.id.expandBtn);
54         expandBtn.setOnClickListener(new OnClickListener() {
55             @Override
56             public void onClick(View v) {
57                 // TODO Auto-generated method stub
58                 expandableListView.expandGroup(3, false);            //展开时,是否执行滑动过程; 建议在测试时,选择展开后列表能够超出屏幕的,更容易看到两者不同
59                 //看源码,发现为true时执行了方法smoothScrollToPosition(position, boundPosition)
60                 //在默认情况下,点击group选项,系统也会执行上述smoothScrollToPosition方法.
61                
62             }
63         });
64 
65     }
函数expandGroup(int groupPos, boolean animate)的执行效果:
              

       默认界面                  animate=false                animate=true

3、注意事项:

a.写布局时,为了去掉系统自带的展开图标(上下箭头),需设置ExpandableListView的android:groupIndicator="@null"

b.可展开列表的适配器一般自定义,并继承自BaseExpandableListAdapter。当然,对于一些简单的数据或布局,可直接使用SimpleExpandableListAdapter或SimpleCursorTreeAdapter。

c.可以让Activity继承ExpandableListActivity,这样在Activity即可重写相关点击事件的方法.因为ExpandableListActivity实现了这些方法的接口。

d.若让子项响应点击事件,必须在ExpandAdapter中设置isChildSelectable()方法返回true。

4、补充:

  上述demo中的子项布局很简单,因为是简单的测试,所以只在布局中定义了一个TextView,图片使用了android:drawableLeft,在ExpandAdapter中可以看到还保留有在代码中设置图片的代码(注释的部分line),以下就总结以下用法:

//子项布局child_view.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="match_parent"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"
     >

    <TextView
        android:id="@+id/child_content"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_marginStart="5dp"
        android:drawableLeft="@drawable/ic_launcher"
        android:ellipsize="end"
        android:gravity="center_vertical"
        android:text="child name"
        android:textSize="20sp"
        android:singleLine="true"
        android:maxLength="30"
         />   

</LinearLayout>

总结:android中,若图标+文字确定的,则可使用TextView一个控件来实现,利用drawableLeft/drawableTop...等。但,若图标不确定,需要在代码中动态设置,则建议分开写,ImageView + TextView 。

   因,在代码中设置图标很麻烦,需要以下三步:
    (1) leftDrawable(获取Drawable对象)
           (2) leftDrawable.setBounds(0, 0, leftDrawable.getMinimumWidth(), leftDrawable.getMinimumHeight());
           (3) childHolder.child_content.setCompoundDrawables(leftDrawable, null, null, null);

 

posted on 2019-07-24 11:33  Android之路  阅读(2321)  评论(0编辑  收藏  举报