分组列表视图(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
2 android:layout_width="match_parent"
3 android:layout_height="match_parent">
4
5
7 android:layout_height="wrap_content"
8 android:id="@+id/elv"/>
9
10
activity_main.xml
2、然后是搭建QQ分组的布局
1
2 android:layout_width="match_parent"
3 android:layout_height="match_parent"
4 android:orientation="vertical" >
5
6
8 android:layout_width="wrap_content"
9 android:layout_height="wrap_content"
10 android:textSize="20sp"
11 android:text="分组名称" />
12
13
15 android:layout_alignParentRight="true"
16 android:layout_width="wrap_content"
17 android:layout_height="wrap_content"
18 android:text="0/8" />
19
20
item_group.xml
3、再搭建分组中各选项的布局(QQ联系人,包括头像,昵称,签名)
这里由于引用了外部的自定义的控件,所以这里包名加类名
1
2 android:layout_width="match_parent"
3 android:layout_height="match_parent"
4 android:layout_gravity="center_vertical"
5 android:orientation="horizontal" >
6
7
9 android:layout_width="80dp"
10 android:layout_height="80dp"
11 android:src="@drawable/ic_launcher" />
12
13
15 android:layout_height="wrap_content"
16 android:layout_marginLeft="10dp"
17 android:orientation="vertical" >
18
19
21 android:layout_width="match_parent"
22 android:layout_height="wrap_content"
23 android:text="昵称"
24 android:textSize="18sp" />
25
26
28 android:layout_height="wrap_content"
29 android:layout_marginTop="10dp"
30 android:orientation="horizontal" >
31
32
34 android:layout_width="wrap_content"
35 android:layout_height="wrap_content"
36 android:text="[在线]" />
37
38
40 android:layout_width="wrap_content"
41 android:layout_height="wrap_content"
42 android:layout_marginLeft="10dp"
43 android:text="我要飞的更高~" />
44
45
46
47
item_child.xml
4、圆角图片形状
在res/values中建circle_attr.xml
1
2
3
4
5
6
7
8
5、然后新建一个CircleImageView继承ImageView
此处自定义控件是在GitHub上下载
1 public class CircleImageView extendsImageView {2 private static finalXfermode MASK_XFERMODE;3 privateBitmap mask;4 privatePaint 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 = newPorterDuffXfermode(localMode);12 }13
14 publicCircleImageView(Context context) {15 super(context);16 }17
18 publicCircleImageView(Context context, AttributeSet attrs) {19 this(context, attrs, 0);20 }21
22 public CircleImageView(Context context, AttributeSet attrs, intdefStyle) {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(booleanuseDefaultStyle) {35 this.useDefaultStyle =useDefaultStyle;36 }37
38 @Override39 protected voidonDraw(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 instanceofNinePatchDrawable) {49 return;50 }51 if (this.paint == null) {52 final Paint localPaint = newPaint();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 intheight) {72 if (mBorderWidth == 0) {73 return;74 }75 final Paint mBorderPaint = newPaint();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 intheight) {86 Bitmap.Config localConfig =Bitmap.Config.ARGB_8888;87 Bitmap localBitmap =Bitmap.createBitmap(width, height, localConfig);88 Canvas localCanvas = newCanvas(localBitmap);89 Paint localPaint = newPaint();90 final int padding = (mBorderWidth - 3) > 0 ? mBorderWidth - 3 : 1;91
92 RectF localRectF = new RectF(padding, padding, width -padding, height93 -padding);94 localCanvas.drawOval(localRectF, localPaint);95
96 returnlocalBitmap;97 }98
99 }
CircleImageView
6、创建Group类
1 public classGroup {2 //分组名
3 publicString groupName;4 //有很多User
5 public Listlist;6
7 publicGroup(String groupName){8 this.groupName =groupName;9 list = new ArrayList();10 }11 //添加User
12 public voidaddUser(User user){13 list.add(user);14 }15
16 //获取某个分组中User的数量
17 public intgetChildCount() {18 returnlist.size();19 }20 //获取某个分组中User在线的数量
21 public intgetOnlineCount(){22 int sum = 0;23 for(User user : list) {24 if(user.isOnline()){25 sum++;26 }27 }28 returnsum;29 }30 //获取分组中某个孩子
31 public User getChild(intchildPosition) {32 returnlist.get(childPosition);33 }34
35
36 }
Group.java
7、创建User类
1 public classUser {2 private intimgId;3 privateString nickName;4 private booleanisOnline;5 privateString sign;6
7
8 publicUser() {9 super();10 }11 public User(int imgId, String nickName, booleanisOnline, String sign) {12 super();13 this.imgId =imgId;14 this.nickName =nickName;15 this.isOnline =isOnline;16 this.sign =sign;17 }18
19 public intgetImgId() {20 returnimgId;21 }22 public void setImgId(intimgId) {23 this.imgId =imgId;24 }25 publicString getNickName() {26 returnnickName;27 }28 public voidsetNickName(String nickName) {29 this.nickName =nickName;30 }31 public booleanisOnline() {32 returnisOnline;33 }34 public void setOnline(booleanisOnline) {35 this.isOnline =isOnline;36 }37 publicString getSign() {38 returnsign;39 }40 public voidsetSign(String sign) {41 this.sign =sign;42 }43
44
45
46
47 }
User
8、设置适配器
1 public class GroupAdapter extendsBaseExpandableListAdapter{2
3 Context context;4 Listlist;5
6 public GroupAdapter(Context context, Listlist) {7 this.context =context;8 this.list =list;9 }10
11 @Override12 public View getGroupView(int groupPosition, booleanisExpanded,13 View convertView, ViewGroup parent) {14 GroupHolder holder;15 if(convertView == null){16 convertView = View.inflate(context, R.layout.item_grouplayout, null);17 holder = newGroupHolder(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 returnconvertView;28 }29
30 @Override31 public View getChildView(int groupPosition, intchildPosition,32 booleanisLastChild, View convertView, ViewGroup parent) {33 ChildHolder holder;34 if(convertView == null){35 convertView = View.inflate(context, R.layout.item_childlayout, null);36 holder = newChildHolder(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 returnconvertView;49
50 }51
52 classGroupHolder{53 TextView groupName;54 TextView groupOnline;55
56 publicGroupHolder(View convertView){57 groupName =(TextView) convertView.findViewById(R.id.groupName);58 groupOnline =(TextView) convertView.findViewById(R.id.groupOnline);59
60 }61 }62 classChildHolder{63 ImageView img;64 TextView nickName;65 TextView online;66 TextView sign;67
68 publicChildHolder(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 @Override79 public intgetGroupCount() {80 returnlist.size();81 }82
83 @Override84 public int getChildrenCount(intgroupPosition) {85 returnlist.get(groupPosition).getChildCount();86 }87
88 @Override89 public Group getGroup(intgroupPosition) {90 returnlist.get(groupPosition);91 }92
93 @Override94 public User getChild(int groupPosition, intchildPosition) {95 returnlist.get(groupPosition).getChild(childPosition);96 }97
98 @Override99 public long getGroupId(intgroupPosition) {100 returngroupPosition;101 }102
103 @Override104 public long getChildId(int groupPosition, intchildPosition) {105 returnchildPosition;106 }107
108 @Override109 public booleanhasStableIds() {110 return true;111 }112
113 @Override114 public boolean isChildSelectable(int groupPosition, intchildPosition) {115 return true;116 }117
118 }
GroupAdapter
9、MainActivity.java中将所有组件找到,初始化数据源,并给ListView设置适配器
1 public class MainActivity extendsActivity {2
3 ExpandableListView elv;4 private List list = new ArrayList();5 int[] img = new int[6];6
7 @Override8 protected voidonCreate(Bundle savedInstanceState) {9 super.onCreate(savedInstanceState);10 setContentView(R.layout.activity_main);11 initData();12 elv =(ExpandableListView) findViewById(R.id.elv);13 GroupAdapter adapter = newGroupAdapter(getBaseContext(), list);14 elv.setAdapter(adapter);15
16 }17
18 private voidinitData() {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
运行效果有点渣渣。请忽略: