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

 

 

運行效果有點渣渣。請忽略:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM