Android ExpandableListView BaseExpandableListAdapter (类似QQ分组列表)

分组列表视图(ExpandableListView)

和ListView不同的是它是一个两级的滚动列表视图,每一个组可以展开,显示一些子项,类似于
QQ列表,这些项目来至于ExpandableListAdapter的子类,也就是说,要实现向里面添加项目,必
须写一个子类实现ExpandableListAdapter的接口或者使用系统为我们实现在子类

   常用属性   

    1. android:childDivider 指定各组内子类表项之间的分隔条,

    2. android:childIndicator 显示在子列表旁边的Drawable对象

    3. android:childIndicatorLeft 子列表项指示符的左边约束位置

    4. android:childIndicatorRight 子列表项指示符的右边约束位置

    5. android:groupIndicator 显示在组列表旁边的Drawable对象

    6. android:indicatorLeft 组列表项指示器的左边约束位置

    7. android:indicatorRight 组列表项指示器的右边约束位置

一般适用于ExpandableListView的Adapter都要继承BaseExpandableListAdapter这个类,
并且必须重载getGroupView和getChildView这两个最为重要的方法。
当扩展BaseExpandableListAdapter时,要实现全部方法,关键是实现其中的四个方法。

1、首相activity_main.xml布局搭建

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent">
 4 
 5     <ExpandableListView
 6         android:layout_width="wrap_content"
 7         android:layout_height="wrap_content"
 8         android:id="@+id/elv"/>
 9 
10 </RelativeLayout>
activity_main.xml

2、然后是搭建QQ分组的布局

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent"
 4     android:orientation="vertical" >
 5 
 6     <TextView
 7         android:id="@+id/groupName"
 8         android:layout_width="wrap_content"
 9         android:layout_height="wrap_content"
10         android:textSize="20sp"
11         android:text="分组名称" />
12 
13     <TextView
14         android:id="@+id/groupOnline"
15         android:layout_alignParentRight="true"
16         android:layout_width="wrap_content"
17         android:layout_height="wrap_content"
18         android:text="0/8" />
19 
20 </RelativeLayout>
item_group.xml

3、再搭建分组中各选项的布局(QQ联系人,包括头像,昵称,签名)

   这里由于引用了外部的自定义的控件,所以这里包名加类名

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent"
 4     android:layout_gravity="center_vertical"
 5     android:orientation="horizontal" >
 6 
 7     <com.test.lesson7_expandablelistview.CircleImageView
 8         android:id="@+id/img"
 9         android:layout_width="80dp"
10         android:layout_height="80dp"
11         android:src="@drawable/ic_launcher" />
12 
13     <LinearLayout
14         android:layout_width="match_parent"
15         android:layout_height="wrap_content"
16         android:layout_marginLeft="10dp"
17         android:orientation="vertical" >
18 
19         <TextView
20             android:id="@+id/nickName"
21             android:layout_width="match_parent"
22             android:layout_height="wrap_content"
23             android:text="昵称"
24             android:textSize="18sp" />
25 
26         <LinearLayout
27             android:layout_width="match_parent"
28             android:layout_height="wrap_content"
29             android:layout_marginTop="10dp"
30             android:orientation="horizontal" >
31 
32             <TextView
33                 android:id="@+id/online"
34                 android:layout_width="wrap_content"
35                 android:layout_height="wrap_content"
36                 android:text="[在线]" />
37 
38             <TextView
39                 android:id="@+id/sign"
40                 android:layout_width="wrap_content"
41                 android:layout_height="wrap_content"
42                 android:layout_marginLeft="10dp"
43                 android:text="我要飞的更高~" />
44         </LinearLayout>
45     </LinearLayout>
46 
47 </LinearLayout>
item_child.xml

4、圆角图片形状

  在res/values中建circle_attr.xml

1 <resources>
2 
3     <declare-styleable name="CircularImage">
4         <attr name="border_width" format="dimension" />
5         <attr name="border_color" format="color" />
6     </declare-styleable>
7 
8 </resources>

5、然后新建一个CircleImageView继承ImageView

  此处自定义控件是在GitHub上下载

 1 public class CircleImageView extends ImageView {
 2     private static final Xfermode MASK_XFERMODE;
 3     private Bitmap mask;
 4     private Paint paint;
 5     private int mBorderWidth = 10;
 6     private int mBorderColor = Color.parseColor("#f2f2f2");
 7     private boolean useDefaultStyle = false;
 8 
 9     static {
10         PorterDuff.Mode localMode = PorterDuff.Mode.DST_IN;
11         MASK_XFERMODE = new PorterDuffXfermode(localMode);
12     }
13 
14     public CircleImageView(Context context) {
15         super(context);
16     }
17 
18     public CircleImageView(Context context, AttributeSet attrs) {
19         this(context, attrs, 0);
20     }
21 
22     public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
23         super(context, attrs, defStyle);
24         TypedArray a = context.obtainStyledAttributes(attrs,
25                 R.styleable.CircularImage);
26         mBorderColor = a.getColor(R.styleable.CircularImage_border_color,
27                 mBorderColor);
28         final int def = (int) (2 * context.getResources().getDisplayMetrics().density + 0.5f);
29         mBorderWidth = a.getDimensionPixelOffset(
30                 R.styleable.CircularImage_border_width, def);
31         a.recycle();
32     }
33 
34     private void useDefaultStyle(boolean useDefaultStyle) {
35         this.useDefaultStyle = useDefaultStyle;
36     }
37 
38     @Override
39     protected void onDraw(Canvas canvas) {
40         if (useDefaultStyle) {
41             super.onDraw(canvas);
42             return;
43         }
44         final Drawable localDraw = getDrawable();
45         if (localDraw == null) {
46             return;
47         }
48         if (localDraw instanceof NinePatchDrawable) {
49             return;
50         }
51         if (this.paint == null) {
52             final Paint localPaint = new Paint();
53             localPaint.setFilterBitmap(false);
54             localPaint.setAntiAlias(true);
55             localPaint.setXfermode(MASK_XFERMODE);
56             this.paint = localPaint;
57         }
58         final int width = getWidth();
59         final int height = getHeight();
60         int layer = canvas.saveLayer(0.0F, 0.0F, width, height, null, 31);
61         localDraw.setBounds(0, 0, width, height);
62         localDraw.draw(canvas);
63         if ((this.mask == null) || (this.mask.isRecycled())) {
64             this.mask = createOvalBitmap(width, height);
65         }
66         canvas.drawBitmap(this.mask, 0.0F, 0.0F, this.paint);
67         canvas.restoreToCount(layer);
68         drawBorder(canvas, width, height);
69     }
70 
71     private void drawBorder(Canvas canvas, final int width, final int height) {
72         if (mBorderWidth == 0) {
73             return;
74         }
75         final Paint mBorderPaint = new Paint();
76         mBorderPaint.setStyle(Paint.Style.STROKE);
77         mBorderPaint.setAntiAlias(true);
78         mBorderPaint.setColor(mBorderColor);
79         mBorderPaint.setStrokeWidth(mBorderWidth);
80         canvas.drawCircle(width / 2, height / 2, (width - mBorderWidth) / 2,
81                 mBorderPaint);
82         canvas = null;
83     }
84 
85     public Bitmap createOvalBitmap(final int width, final int height) {
86         Bitmap.Config localConfig = Bitmap.Config.ARGB_8888;
87         Bitmap localBitmap = Bitmap.createBitmap(width, height, localConfig);
88         Canvas localCanvas = new Canvas(localBitmap);
89         Paint localPaint = new Paint();
90         final int padding = (mBorderWidth - 3) > 0 ? mBorderWidth - 3 : 1;
91 
92         RectF localRectF = new RectF(padding, padding, width - padding, height
93                 - padding);
94         localCanvas.drawOval(localRectF, localPaint);
95 
96         return localBitmap;
97     }
98 
99 }
CircleImageView

6、创建Group类

 1 public class Group {
 2     //分组名
 3     public String groupName;
 4     //有很多User
 5     public List<User> list;
 6     
 7     public Group(String groupName){
 8         this.groupName = groupName;
 9         list = new ArrayList<User>();
10     }
11     //添加User
12     public void addUser(User user){
13         list.add(user);
14     }
15     
16     //获取某个分组中User的数量
17     public int getChildCount() {
18         return list.size();
19     }
20     //获取某个分组中User在线的数量
21     public int getOnlineCount(){
22         int sum = 0;
23         for (User user : list) {
24             if(user.isOnline()){
25                 sum++;
26             }
27         }
28         return sum;
29     }
30     //获取分组中某个孩子
31     public User getChild(int childPosition) {
32         return list.get(childPosition);
33     }
34     
35     
36 }
Group.java

7、创建User类

 1 public class User {
 2     private int imgId;
 3     private String nickName;
 4     private boolean isOnline;
 5     private String sign;
 6     
 7     
 8     public User() {
 9         super();
10     }
11     public User(int imgId, String nickName, boolean isOnline, String sign) {
12         super();
13         this.imgId = imgId;
14         this.nickName = nickName;
15         this.isOnline = isOnline;
16         this.sign = sign;
17     }
18     
19     public int getImgId() {
20         return imgId;
21     }
22     public void setImgId(int imgId) {
23         this.imgId = imgId;
24     }
25     public String getNickName() {
26         return nickName;
27     }
28     public void setNickName(String nickName) {
29         this.nickName = nickName;
30     }
31     public boolean isOnline() {
32         return isOnline;
33     }
34     public void setOnline(boolean isOnline) {
35         this.isOnline = isOnline;
36     }
37     public String getSign() {
38         return sign;
39     }
40     public void setSign(String sign) {
41         this.sign = sign;
42     }
43     
44     
45     
46     
47 }
User

8、设置适配器

  1 public class GroupAdapter extends BaseExpandableListAdapter{
  2 
  3     Context context;
  4     List<Group> list;
  5     
  6     public GroupAdapter(Context context, List<Group> list) {
  7         this.context = context;
  8         this.list = list;
  9     }
 10     
 11     @Override
 12     public View getGroupView(int groupPosition, boolean isExpanded,
 13             View convertView, ViewGroup parent) {
 14         GroupHolder holder;
 15         if(convertView == null){
 16             convertView = View.inflate(context, R.layout.item_grouplayout, null);
 17             holder = new GroupHolder(convertView);
 18             convertView.setTag(holder);
 19         }else{
 20             holder = (GroupHolder) convertView.getTag();
 21         }
 22         //设置数据
 23         Group group = getGroup(groupPosition);
 24         holder.groupName.setText(group.groupName);
 25         holder.groupOnline.setText(group.getOnlineCount()+"/"+getChildrenCount(groupPosition));
 26         
 27         return convertView;
 28     }
 29 
 30     @Override
 31     public View getChildView(int groupPosition, int childPosition,
 32             boolean isLastChild, View convertView, ViewGroup parent) {
 33         ChildHolder holder;
 34         if(convertView == null){
 35             convertView = View.inflate(context, R.layout.item_childlayout, null);
 36             holder = new ChildHolder(convertView);
 37             convertView.setTag(holder);
 38         }else{
 39             holder = (ChildHolder) convertView.getTag();
 40         }
 41         //设置数据
 42         User user = getGroup(groupPosition).getChild(childPosition);
 43         holder.img.setImageResource(user.getImgId());
 44         holder.nickName.setText(user.getNickName());
 45         holder.online.setText(user.isOnline()?"[在线]":"[离线]");
 46         holder.sign.setText(user.getSign());
 47         
 48         return convertView;
 49         
 50     }
 51     
 52     class GroupHolder{
 53         TextView groupName;
 54         TextView groupOnline;
 55         
 56         public GroupHolder(View convertView){
 57             groupName = (TextView) convertView.findViewById(R.id.groupName);
 58             groupOnline = (TextView) convertView.findViewById(R.id.groupOnline);
 59             
 60         }
 61     }
 62     class ChildHolder{
 63         ImageView img;
 64         TextView nickName;
 65         TextView online;
 66         TextView sign;
 67         
 68         public ChildHolder(View convertView){
 69             img = (ImageView) convertView.findViewById(R.id.img);
 70             nickName = (TextView) convertView.findViewById(R.id.nickName);
 71             online = (TextView) convertView.findViewById(R.id.online);
 72             sign = (TextView) convertView.findViewById(R.id.sign);
 73             
 74         }
 75         
 76     }
 77     
 78     @Override
 79     public int getGroupCount() {
 80         return list.size();
 81     }
 82 
 83     @Override
 84     public int getChildrenCount(int groupPosition) {
 85         return list.get(groupPosition).getChildCount();
 86     }
 87 
 88     @Override
 89     public Group getGroup(int groupPosition) {
 90         return list.get(groupPosition);
 91     }
 92 
 93     @Override
 94     public User getChild(int groupPosition, int childPosition) {
 95         return list.get(groupPosition).getChild(childPosition);
 96     }
 97 
 98     @Override
 99     public long getGroupId(int groupPosition) {
100         return groupPosition;
101     }
102 
103     @Override
104     public long getChildId(int groupPosition, int childPosition) {
105         return childPosition;
106     }
107 
108     @Override
109     public boolean hasStableIds() {
110         return true;
111     }
112 
113     @Override
114     public boolean isChildSelectable(int groupPosition, int childPosition) {
115         return true;
116     }
117 
118 }
GroupAdapter

9、MainActivity.java中将所有组件找到,初始化数据源,并给ListView设置适配器

 1 public class MainActivity extends Activity {
 2 
 3     ExpandableListView elv;
 4     private List<Group> list = new ArrayList<Group>();
 5     int[] img = new int[6];
 6     
 7     @Override
 8     protected void onCreate(Bundle savedInstanceState) {
 9         super.onCreate(savedInstanceState);
10         setContentView(R.layout.activity_main);
11         initData();
12         elv = (ExpandableListView) findViewById(R.id.elv);
13         GroupAdapter adapter = new GroupAdapter(getBaseContext(), list);
14         elv.setAdapter(adapter);
15         
16     }
17 
18     private void initData() {
19         for (int i = 0; i < img.length; i++) {
20             try {
21                 img[i] = R.drawable.class.getField("img0"+(i+1)).getInt(null);
22             } catch (Exception e) {
23                 e.printStackTrace();
24             }
25         }
26         
27         Group group1 = new Group("贵圈好乱");
28         group1.addUser(new User(img[0], "张翰", true, "我爱娜扎!"));
29         group1.addUser(new User(img[1], "郑爽", false, "妈蛋,要么瘦,要么死!"));
30         group1.addUser(new User(img[2], "胡彦斌", true, "其实我只是长得抽象了"));
31         group1.addUser(new User(img[5], "撒贝宁", true, "子怡当年没选择我是个美丽的错误"));
32         group1.addUser(new User(img[3], "杨幂", false, "其实我跟恺威已经离婚了,现在跟李易峰在一起,就酱~"));
33         
34         Group group2 = new Group("超星星");
35         group2.addUser(new User(img[4], "林志炫", true, "其实我的小肚子都是唱歌导致的,哈哈哈"));
36         
37         list.add(group1);
38         list.add(group2);
39         
40     }
41     
42     
43 }
MainActivity.java

运行效果有点渣渣。请忽略:

原文地址:https://www.cnblogs.com/Claire6649/p/5955713.html