Android中使用ExpandableListView實現微信通訊錄界面(完善仿微信APP)

来源:http://www.cnblogs.com/panhouye/archive/2016/12/29/6231599.html
-Advertisement-
Play Games

之前的博文《Android中使用ExpandableListView實現好友分組》我簡單介紹了使用ExpandableListView實現簡單的好友分組功能,今天我們針對之前的所做的仿微信APP來對ExpandableListView做一個擴展介紹,實現效果如下(通訊里使用ExpandableLis ...


之前的博文《Android中使用ExpandableListView實現好友分組》我簡單介紹了使用ExpandableListView實現簡單的好友分組功能,今天我們針對之前的所做的仿微信APP來對ExpandableListView做一個擴展介紹,實現效果如下(通訊里使用ExpandableListView實現):

相關知識點博文鏈接:

Android中使用ExpandableListView實現好友分組

Android中Fragment和ViewPager那點事兒

Android中ListView實現圖文併列並且自定義分割線(完善仿微信APP)

正常使用ExpandableListView的思路如下:

(1)要給ExpandableListView 設置適配器,那麼必須先設置數據源。

(2)數據源,就是此處的適配器類ExpandableAdapter,此方法繼承了BaseExpandableListAdapter ,它是ExpandableListView的一個子類。需要重寫裡面的多個方法。方法的意思,代碼中都有詳細的註釋。數據源中,用到了自定義的View佈局,此時根據自己的需求,來設置組和子項的佈局樣式。getChildView()和getGroupView()方法設置自定義佈局。
(3)數據源設置好,直接給 ExpandableListView.setAdapter()即可實現此收縮功能。

但本次實現除以上實現步驟之外,還需要註意的有以下幾點:

(1)首次載入ExpandableListView需要預設全部展開,使用以下方法: 在給ExpandableListView 設置適配器後,添加以下代碼:
1 //Group.size()為組名個數,如果為數組存儲則為group、length
2 for (int i = 0; i < Group.size(); i++) { 
3     expandableListView.expandGroup(i); 
4 } 
提醒:載入前別忘了判斷adapter是否為空和有沒有Group數據哦

(2)保持ExpandableListView始終展開無法收縮

1 expandableListView.setOnGroupClickListener(new OnGroupClickListener() {
2     @Override
3     public boolean onGroupClick(ExpandableListView parent, View v,
4         int groupPosition, long id) {
5         return true;//返回true則表示無法收縮
6     }
7 });
(3)取消通訊錄上方的groupName空間 微信通訊錄中“新的朋友”,“群聊”,“標簽”,“公眾號”,作為一個整體自定義佈局添加到ExpandableListView中,詳情見以下代碼實現 (4)修改ExpandableListView的分割線 大概思路就是這樣,現在開始整體實現代碼的演示:

第一步:layout中通訊錄整體佈局contactfragment.xml:

其實就是一個ExpandableListView,添加android:divider ="#FFFFFF"取消自帶分割線

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:orientation="vertical" android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:background="@color/fragmentback">
 6     <ExpandableListView
 7         android:id="@+id/contact_list"
 8         android:layout_width="match_parent"
 9         android:layout_height="match_parent"
10         android:layout_alignParentTop="true"
11         android:layout_alignParentStart="true"
12         android:divider ="#FFFFFF"/>
13 </LinearLayout>

第二步:layout中組名(groupName)的佈局文件contact_list_group_item.xml:

註意設置間距,保證美觀且儘量與微信一致

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:orientation="vertical" android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:background="@color/fragmentback">
 6     <TextView
 7         android:text="TextView"
 8         android:textSize="20sp"
 9         android:layout_width="match_parent"
10         android:layout_height="wrap_content"
11         android:layout_marginLeft="10dp"
12         android:gravity="center_vertical"
13         android:id="@+id/group_tv" />
14 </LinearLayout>

第三步:layout中ExpandableListView中每個item的佈局文件contact_list_item.xml:

這裡添加了自定義分割線
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:orientation="vertical" android:layout_width="match_parent"
 4     android:layout_height="match_parent">
 5     <LinearLayout
 6         android:background="@color/colorwhite"
 7         android:layout_width="match_parent"
 8         android:layout_height="match_parent"
 9         android:orientation="vertical">
10         <LinearLayout
11             android:paddingLeft="10dp"
12             android:paddingTop="5dp"
13             android:paddingBottom="5dp"
14             android:gravity="center_vertical"
15             android:layout_width="match_parent"
16             android:layout_height="wrap_content"
17             android:orientation="horizontal">
18             <ImageView
19                 android:id="@+id/contact_item_iv"
20                 android:layout_width="wrap_content"
21                 android:layout_height="wrap_content"
22                 android:src="@mipmap/default_fmessage"
23                 android:adjustViewBounds="true"
24                 android:maxWidth="35dp"/>
25             <TextView
26                 android:id="@+id/contact_item_tv"
27                 android:layout_margin="10dp"
28                 android:layout_width="0dp"
29                 android:layout_height="wrap_content"
30                 android:layout_weight="1"
31                 android:text="新的朋友"/>
32         </LinearLayout>
33         <View
34             android:layout_width="match_parent"
35             android:layout_height="1dp"
36             android:layout_marginLeft="10dp"
37             android:layout_marginRight="10dp"
38             android:background="@color/fragmentback"/>
39     </LinearLayout>
40 </LinearLayout>

第四步:layout中ExpandableListView中的頭佈局contact_list_title.xml(不需要groupName)

我們觀察微信通訊錄佈局中“新的朋友”,“群聊”,“標簽”,“公眾號”上方直接為微信的頂部導航,不存在ExpandableListView一貫的組名佈局,這裡我們將 “新的朋友”,“群聊”,“標簽”的佈局單獨實現:
  1 <?xml version="1.0" encoding="utf-8"?>
  2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3     android:orientation="vertical" android:layout_width="match_parent"
  4     android:layout_height="match_parent">
  5         <LinearLayout
  6             android:background="@color/colorwhite"
  7             android:layout_width="match_parent"
  8             android:layout_height="match_parent"
  9             android:orientation="vertical">
 10             <LinearLayout
 11                 android:paddingLeft="10dp"
 12                 android:paddingTop="5dp"
 13                 android:paddingBottom="5dp"
 14                 android:gravity="center_vertical"
 15                 android:layout_width="match_parent"
 16                 android:layout_height="wrap_content"
 17                 android:orientation="horizontal">
 18                 <ImageView
 19                     android:layout_width="wrap_content"
 20                     android:layout_height="wrap_content"
 21                     android:src="@mipmap/default_fmessage"
 22                     android:adjustViewBounds="true"
 23                     android:maxWidth="35dp"/>
 24                 <TextView
 25                     android:layout_margin="10dp"
 26                     android:layout_width="0dp"
 27                     android:layout_height="wrap_content"
 28                     android:layout_weight="1"
 29                     android:text="新的朋友"/>
 30             </LinearLayout>
 31             <View
 32                 android:layout_width="match_parent"
 33                 android:layout_height="1dp"
 34                 android:layout_marginLeft="10dp"
 35                 android:layout_marginRight="10dp"
 36                 android:background="@color/fragmentback"/>
 37             <LinearLayout
 38                 android:paddingLeft="10dp"
 39                 android:paddingTop="5dp"
 40                 android:paddingBottom="5dp"
 41                 android:gravity="center_vertical"
 42                 android:layout_width="match_parent"
 43                 android:layout_height="wrap_content"
 44                 android:orientation="horizontal">
 45                 <ImageView
 46                     android:layout_width="wrap_content"
 47                     android:layout_height="wrap_content"
 48                     android:src="@mipmap/default_chatroom"
 49                     android:adjustViewBounds="true"
 50                     android:maxWidth="35dp"/>
 51                 <TextView
 52                     android:layout_margin="10dp"
 53                     android:layout_width="0dp"
 54                     android:layout_height="wrap_content"
 55                     android:layout_weight="1"
 56                     android:text="群聊"/>
 57             </LinearLayout>
 58             <View
 59                 android:layout_width="match_parent"
 60                 android:layout_height="1dp"
 61                 android:layout_marginLeft="10dp"
 62                 android:layout_marginRight="10dp"
 63                 android:background="@color/fragmentback"/>
 64             <LinearLayout
 65                 android:paddingLeft="10dp"
 66                 android:paddingTop="5dp"
 67                 android:paddingBottom="5dp"
 68                 android:gravity="center_vertical"
 69                 android:layout_width="match_parent"
 70                 android:layout_height="wrap_content"
 71                 android:orientation="horizontal">
 72                 <ImageView
 73                     android:layout_width="wrap_content"
 74                     android:layout_height="wrap_content"
 75                     android:src="@mipmap/default_contactlabel"
 76                     android:adjustViewBounds="true"
 77                     android:maxWidth="35dp"/>
 78                 <TextView
 79                     android:layout_margin="10dp"
 80                     android:layout_width="0dp"
 81                     android:layout_height="wrap_content"
 82                     android:layout_weight="1"
 83                     android:text="標簽"/>
 84             </LinearLayout>
 85             <View
 86                 android:layout_width="match_parent"
 87                 android:layout_height="1dp"
 88                 android:layout_marginLeft="10dp"
 89                 android:layout_marginRight="10dp"
 90                 android:background="@color/fragmentback"/>
 91             <LinearLayout
 92                 android:paddingLeft="10dp"
 93                 android:paddingTop="5dp"
 94                 android:paddingBottom="5dp"
 95                 android:gravity="center_vertical"
 96                 android:layout_width="match_parent"
 97                 android:layout_height="wrap_content"
 98                 android:orientation="horizontal">
 99                 <ImageView
100                     android:layout_width="wrap_content"
101                     android:layout_height="wrap_content"
102                     android:src="@mipmap/default_servicebrand_contact"
103                     android:adjustViewBounds="true"
104                     android:maxWidth="35dp"/>
105                 <TextView
106                     android:layout_margin="10dp"
107                     android:layout_width="0dp"
108                     android:layout_height="wrap_content"
109                     android:layout_weight="1"
110                     android:text="公眾號"/>
111             </LinearLayout>
112         </LinearLayout>
113 </LinearLayout>

第五步:java中定義繼承BaseExpandableListAdapter類(自定義適配器)

(1)這裡模仿實際項目,將自定義適配器定義定義在外部同意管理,所以需要設置相關構造方法供expandableListView調用 (2)為了實現頭文件的佈局,需要在getGroupView與getChildView方法中判斷頭文件的位置,從而調整佈局,這裡我們將頭文件定義在數據首位
  1 import android.content.Context;
  2 import android.view.LayoutInflater;
  3 import android.view.View;
  4 import android.view.ViewGroup;
  5 import android.widget.BaseExpandableListAdapter;
  6 import android.widget.ImageView;
  7 import android.widget.TextView;
  8 import com.mly.panhouye.wechat.R;
  9 /**
 10  * Created by panchengjia on 2016/12/28 0028.
 11  */
 12 public class MyExpandableListAdapter extends BaseExpandableListAdapter {
 13     Context context;
 14     String[] group;
 15     String[][] itemName;
 16     int[][] itemIcon;
 17     public MyExpandableListAdapter(Context context, String[] group, String[][] itemName, int[][] itemIcon) {
 18         this.context = context;
 19         this.group = group;
 20         this.itemName = itemName;
 21         this.itemIcon = itemIcon;
 22     }
 23 
 24     @Override
 25     public int getGroupCount() {
 26         return group.length;
 27     }
 28 
 29     @Override
 30     public int getChildrenCount(int groupPosition) {
 31         return itemName[groupPosition].length;
 32     }
 33 
 34     @Override
 35     public Object getGroup(int groupPosition) {
 36         return group[groupPosition];
 37     }
 38 
 39     @Override
 40     public Object getChild(int groupPosition, int childPosition) {
 41         return itemName[groupPosition][childPosition];
 42     }
 43 
 44     @Override
 45     public long getGroupId(int groupPosition) {
 46         return groupPosition;
 47     }
 48 
 49     @Override
 50     public long getChildId(int groupPosition, int childPosition) {
 51         return childPosition;
 52     }
 53 
 54     @Override
 55     public boolean hasStableIds() {
 56         return false;
 57     }
 58 
 59     @Override
 60     public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
 61         ViewHolder vh;
 62         //ExpandableList的第一個分組沒有組名,這裡需要自定義佈局
 63         if(groupPosition==0){
 64             convertView =LayoutInflater.from(context).inflate(R.layout.contact_list_title,null);
 65         }else{
 66             if(convertView==null){
 67                 convertView= LayoutInflater.from(context).inflate(R.layout.contact_list_group_item,null);
 68                 vh = new ViewHolder();
 69                 vh.tv = (TextView) convertView.findViewById(R.id.group_tv);
 70                 convertView.setTag(vh);
 71             }
 72             vh = (ViewHolder) convertView.getTag();
 73 
 74             vh.tv.setText(group[groupPosition]);
 75         }
 76 
 77         return convertView;
 78     }
 79 
 80     @Override
 81     public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
 82         ViewHolder vh;
 83         //ExpandableList的第一個分組沒有組名,這裡需要自定義佈局
 84         if (groupPosition==0){
 85             convertView =LayoutInflater.from(context).inflate(R.layout.contact_list_title,null);
 86         }else{
 87             if(convertView==null){
 88                 convertView= LayoutInflater.from(context).inflate(R.layout.contact_list_item,null);
 89                 vh = new ViewHolder();
 90                 vh.tv = (TextView) convertView.findViewById(R.id.contact_item_tv);
 91                 vh.iv= (ImageView) convertView.findViewById(R.id.contact_item_iv);
 92                 convertView.setTag(vh);
 93             }
 94             vh = (ViewHolder) convertView.getTag();
 95             vh.tv.setText(itemName[groupPosition][childPosition]);
 96             vh.iv.setImageResource(itemIcon[groupPosition][childPosition]);
 97         }
 98         return convertView;
 99     }
100     @Override
101     public boolean isChildSelectable(int groupPosition, int childPosition) {
102         return true;
103     }
104     class ViewHolder{
105         TextView tv;
106         ImageView iv;
107     }
108 }

第六步:java中重寫之前的與contactfragment.xml佈局對應的ContactFragment.java類

 1 import android.os.Bundle;
 2 import android.support.annotation.Nullable;
 3 import android.support.v4.app.Fragment;
 4 import android.view.LayoutInflater;
 5 import android.view.View;
 6 import android.view.ViewGroup;
 7 import android.widget.ExpandableListView;
 8 import com.mly.panhouye.wechat.R;
 9 import com.mly.panhouye.wechat.adapter.MyExpandableListAdapter;
10 
11 /**
12  * Created by panchengjia on 2016/12/28 0028.
13  */
14 
15 public class ContactFragment extends Fragment {
16     private ExpandableListView contact_list;
17     //定義分組以及組內成員(設置頭文件位置為空)
18     String[] group ={"","好友列表"};
19     String[][] itemName={{},{"郭嘉", "黃月英", "華佗",
20             "劉備", "陸遜", "呂布", "呂蒙", "馬超", "司馬懿", "孫權", "孫尚香", "夏侯惇",
21             "許褚", "楊修", "張飛", "趙雲", "甄姬", "周瑜", "諸葛亮"}};
22     int[][] itemIcon={{},{R.mipmap.guojia,
23             R.mipmap.huangyueying, R.mipmap.huatuo,
24             R.mipmap.liubei, R.mipmap.luxun, R.mipmap.lvbu, R.mipmap.lvmeng,
25             R.mipmap.machao, R.mipmap.simayi, R.mipmap.sunquan, R.mipmap.sunshangxiang,
26             R.mipmap.xiahoudun, R.mipmap.xuchu, R.mipmap.yangxiu, R.mipmap.zhangfei,
27             R.mipmap.zhaoyun, R.mipmap.zhenji, R.mipmap.zhouyu, R.mipmap.zhugeliang}};
28     @Override
29     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
30         View view = inflater.inflate(R.layout.contact_fragment,container,false);
31         contact_list = (ExpandableListView) view.findViewById(R.id.contact_list);
32         //實例化適配器
33         MyExpandableListAdapter myExpandableListAdapter=new MyExpandableListAdapter(getContext(),group,itemName,itemIcon);
34         //配置適配器
35         contact_list.setAdapter(myExpandableListAdapter);
36         //去掉ExpandableListView 預設的箭頭
37         contact_list.setGroupIndicator(null);
38         //設置ExpandableListView預設展開
39         for (int i = 0; i <group.length; i++) {
40             contact_list.expandGroup(i);
41         }
42         //設置ExpandableListView不可點擊收回
43         contact_list.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
44             @Override
45             public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
46                 return true;
47             }
48         });
49         return view;
50     }
51 }

實現方法很多大家開動吧(建議使用recyclerView),我先睡了。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 由[OpenDigg](http://www.opendigg.com/) 出品的iOS開源項目周報第三期來啦。我們的iOS開源周報集合了OpenDigg一周來新收錄的優質的iOS開發方面的開源項目,方便iOS開發人員便捷的找到自己需要的項目工具等。 ...
  • 摘要:我們來瞭解一下MVVM模式與Databinding ,MVVM是一種模式,Databinding 是一種框架。DataBinding是一個實現數據和UI綁定的框架。而ViewModel和View可以通過DataBinding來實現單向綁定和雙向綁定,這套UI和數據之間的動態監聽和動態更新的框架 ...
  • 提到FlexboxLayout大家估計有點模糊,它是谷歌最近開源的一個android排版庫,它的前身Flexbox是2009年W3C提出了一種新的佈局,可以簡便、完整、響應式的實現頁面佈局,Flexbox 是屬於web前端領域CSS的一種佈局方案。 首先:我們看一下它的屬性。 flexDirecti ...
  • 大致分為以下幾個方面: 一些查詢指令整理 使用SQL語句進行特殊查詢 檢測表欄位是否存在 資料庫升級 資料庫表欄位賦初始值 一、查詢指令整理 1.鏈式執行的指令 一般的查詢語句會在中間xxx的位置加上各種判斷和過濾的方法指令,除了最後的終結指令list()或unique()返回的是集合或業務對象,其 ...
  • 微信的張小龍也說了,小程式主要是通過二維碼進行傳播,那麼小程式的二維碼如何統計各個渠道的值呢? 微信小程式開發了帶參數二維碼,而帶參數二維碼就可以進行渠道統計 不然我有3個人,讓3個人使用不同的小程式二維碼進行地推 地推人員A 二維碼A 參數hotapp=a 地推人員B 二維碼B 參數hotapp= ...
  • 最近在學習安卓APP的開發,用到了toolbar這個控制項, 最開始使用時include layout這種方法,不過感覺封裝性不好,就又改成了自定義組合控制項的方式。 使用的工具為android studio 2.2,簡稱AS吧 1.首先創建一個新的自定義控制項,如下圖。AS會創建3個文件, 一個java ...
  • 新項目用swift3.0開發,現在基本一個月,來總結一下遇到的問題及解決方案 1,在確定新項目用swift後,第一個考慮的問題是用純swift呢?還是用swift跟OC混編 考慮到新項目也不可避免的使用很多第三方庫,而第三方庫不一定支持swift或者有swift的替代版本,所以最終還是決定混編了; ...
  • Android游戲開發實踐(1)之NDK與JNI開發03 前面已經分享了兩篇有關Android平臺NDK與JNI開發相關的內容。以下列舉前面兩篇的鏈接地址,感興趣的可以再回顧下。那麼,這篇繼續這個小專題,主要分享下AndroidStudio下的NDK與JNI開發的相關操作以及簡述下CMake的使用。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...