Android開發系列(九) ExpandableListView進階使用——QQ聯系人列表(升級版)


  本節繼續講ExpandableListView的使用,與系列(六)中類似,這里需要寫一個自定義的適配器類繼承BaseExpandableListAdapter, 並且對QQ聯系人列表進行升級,使之具有對聯系人分類的功能,即可以分成"我的好友","朋友","陌生人"等等類別。如果對第六節的內容給比較熟悉,可以完全根據那個思路構造出自己的適配器類,實際上我在寫這節內容之前並沒有參考網上的資料慢慢摸索出來的。

首先是布局文件,

activity_main.xml 主布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:background="#00aaff"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/myText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="聯系人"
        android:textSize="7pt"
        android:layout_centerHorizontal="true"
        android:textColor="#ffffff"
        android:textStyle="bold" />
    <ExpandableListView
        android:id="@+id/qq_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/myText"
        android:divider="#888888"
        android:dividerHeight="0.15px"/>
   
</RelativeLayout>

一級條目的布局文件 layout_group.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="wrap_content"
    android:paddingLeft="5dip"
    android:orientation="horizontal" 
    android:background="#eeeeee">

    <ImageView
        android:id="@+id/groupImage"
        android:layout_width="match_parent"
        android:layout_height="15dip"
        android:layout_weight="1.8"
        android:layout_gravity="center" />

    <TextView
        android:id="@+id/groupName"
        android:layout_width="match_parent"
        android:layout_height="30dip"
        android:layout_weight="1"
        android:paddingLeft="15dip"
        android:paddingTop="5dip"
        android:textSize="7pt"
        android:text="fdg" />
    <TextView 
        android:id="@+id/childCount"
        android:layout_width="match_parent"
        android:layout_height="30dip"
        android:layout_weight="1"
        android:gravity="right"
        android:paddingRight="10dip"
        android:paddingTop="5dip"
        android:text="ewsf"/>

</LinearLayout>

二級條目的布局文件layout_child.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#efefef" >
    
    <!-- LinerLayout有比較奇怪的性質:當布局中的控件可以超出布局規定的大小 ,所以這里一行的行寬改成由內部的幾個控件
    控制,而LinerLayout的layout_height改成wrap_content ..  -->
    
    
    <ImageButton 
        android:id="@+id/ct_photo"
        android:layout_height="70dip"
        android:layout_width="70dip"
        android:layout_margin="5dip"/>
    <TextView 
        android:id="@+id/ct_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dip"
        android:layout_toRightOf="@id/ct_photo"
        android:layout_alignTop="@id/ct_photo"
        android:text="為你我受冷風吹"
        android:textSize="8pt"
        android:textStyle="bold"
        android:maxLength="7"/>
    
    <TextView 
        android:id="@+id/ct_sign"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dip"
        android:layout_toRightOf="@id/ct_photo"
        android:layout_alignBottom="@id/ct_photo"
        android:text="為什么受傷的總是我"
        android:textColor="#888888"/>
    <!-- 注意不是layout_padding -->
    
    
    
    

</RelativeLayout>

 

下面就是自定義的適配器類,為了和Simple適配器參數相同,這里采用了類似的構造函數。

package com.example.android_baseexpandablelistview;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.*;

import java.util.*;


public class MyAdapter extends BaseExpandableListAdapter{
    
    private Context context=null;
    private ArrayList<HashMap<String,Object>> groupData=null;
    int groupLayout=0;
    private String[] groupFrom=null;
    private int[] groupTo=null;
    private ArrayList<ArrayList<HashMap<String,Object>>> childData=null;
    int childLayout=0;
    private String[] childFrom=null;
    private int[] childTo=null;
    
    
    

    public MyAdapter(Context context, ArrayList<HashMap<String, Object>> groupData,
            int groupLayout, String[] groupFrom, int[] groupTo,
            ArrayList<ArrayList<HashMap<String, Object>>> childData, int childLayout,
            String[] childFrom, int[] childTo) {
        super();
        this.context = context;
        this.groupData = groupData;
        this.groupLayout = groupLayout;
        this.groupFrom = groupFrom;
        this.groupTo = groupTo;
        this.childData = childData;
        this.childLayout = childLayout;
        this.childFrom = childFrom;
        this.childTo = childTo;
    }

    @Override
    public Object getChild(int arg0, int arg1) {
        // TODO Auto-generated method stub
        return null;
    }

    /**
     * position與id一樣,都是從0開始計數的,
     * 這里返回的id也是從0開始計數的
     */
    @Override
    public long getChildId(int groupPosition, int childPosition) {
        // TODO Auto-generated method stub
        long id=0;
        for(int i=0;i<groupPosition; i++){
            id+=childData.size();
        }
        id+=childPosition;  
        return id;           
    }
    
    /**ChildViewHolder內部類**/
    class ChildViewHolder{
        ImageButton userImage=null;
        TextView userName=null;
        TextView userSign=null;
    }
    
    /**頭像點擊事件監聽類**/
    class ImageClickListener implements OnClickListener{

        ChildViewHolder holder=null;
        public ImageClickListener(ChildViewHolder holder){
            this.holder=holder;
        }
        
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Toast.makeText(context, holder.userName.getText()+" is clicked", Toast.LENGTH_SHORT).show();
            
        }
        
    }

    
    
    @Override
    public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        /**
         * 這里isLastChild目前沒用到,如果出現異常再說
         */
        ChildViewHolder holder=null;
        if(convertView==null){
            convertView= LayoutInflater.from(context).inflate(childLayout,null);
                                         //感覺這里需要把root設置成ViewGroup 對象
            /**
             * ERROR!!這里不能把null換成parent,否則會出現異常退出,原因不太確定,可能是inflate方法獲得的這個item的View
             * 並不屬於某個控件組,所以使用默認值null即可
             */
            holder=new ChildViewHolder();
            holder.userImage=(ImageButton)convertView.findViewById(childTo[0]);
            holder.userName=(TextView)convertView.findViewById(childTo[1]);
            holder.userSign=(TextView)convertView.findViewById(childTo[2]);
            convertView.setTag(holder);
        }
        else{
            holder=(ChildViewHolder)convertView.getTag();
        }
        
        holder.userImage.setBackgroundResource((Integer)(childData.get(groupPosition).get(childPosition).get(childFrom[0])));
        holder.userName.setText(childData.get(groupPosition).get(childPosition).get(childFrom[1]).toString());
        holder.userSign.setText(childData.get(groupPosition).get(childPosition).get(childFrom[2]).toString());
        holder.userImage.setOnClickListener(new ImageClickListener(holder));
        
        return convertView;
    }

    
    @Override
    public int getChildrenCount(int groupPosition) {
        // TODO Auto-generated method stub
        return childData.get(groupPosition).size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int getGroupCount() {
        // TODO Auto-generated method stub
        return groupData.size();
    }

    @Override
    public long getGroupId(int groupPosition) {
        // TODO Auto-generated method stub
        return groupPosition;
    }

    
    class GroupViewHolder{
        ImageView image=null;
        TextView groupName=null;
        TextView childCount=null;
    }
    
    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,
            View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        GroupViewHolder holder=null;
        if(convertView==null){
            convertView=LayoutInflater.from(context).inflate(groupLayout, null);
            holder=new GroupViewHolder();
            holder.image=(ImageView)convertView.findViewById(groupTo[0]);
            holder.groupName=(TextView)convertView.findViewById(groupTo[1]);
            holder.childCount=(TextView)convertView.findViewById(groupTo[2]);
            convertView.setTag(holder);
        }
        else{
            holder=(GroupViewHolder)convertView.getTag();
        }
        
        int[] groupIndicator=(int[])groupData.get(groupPosition).get(groupFrom[0]);
        holder.image.setBackgroundResource(groupIndicator[isExpanded?1:0]);
        holder.groupName.setText(groupData.get(groupPosition).get(groupFrom[1]).toString());
        holder.childCount.setText(groupData.get(groupPosition).get(groupFrom[2]).toString());
        
        return convertView;
        /**
         * 不要在適配器中調用適配器的內部方法,不然會出現奇怪的異常
         * 
         */
    }

    @Override
    public boolean hasStableIds() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        // TODO Auto-generated method stub
        return true;
    }

}

 

  由上一節的內容可知為適配器添加數據非常麻煩,因此這里創建了一個 QQ用戶類,用來存放一個QQ用戶的各種信息,然后在MainActivity中設計了一個將新QQ用戶對象添加進List數據鏈表中的方法,見下面:

package com.qqlist.contactor;

public class UserInfo {
    public String userName=null;
    public String userSign=null;
    public int userImage=0;
    public String groupInfo=null;
    public UserInfo(String userName, String userSign, int userImage,
            String groupInfo) {
        super();
        this.userName = userName;
        this.userSign = userSign;
        this.userImage = userImage;
        this.groupInfo = groupInfo;
    }
    
    

}

 

然后是MainActivity

package com.example.android_baseexpandablelistview;


import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.ExpandableListView;

import java.util.*;

import com.qqlist.contactor.UserInfo;

public class MainActivity extends Activity {

    
    int[] photoRes={R.drawable.contact_0,R.drawable.contact_1,R.drawable.contact_2,R.drawable.contact_3};
    
    String[] groupFrom={"groupImage","groupName","childCount"};
    int[] groupTo={R.id.groupImage,R.id.groupName,R.id.childCount};
    String[] childFrom={"userImage","userName","userSign"};
    int[] childTo={R.id.ct_photo,R.id.ct_name,R.id.ct_sign};
    ArrayList<HashMap<String,Object>> groupData=null;
    ArrayList<ArrayList<HashMap<String,Object>>> childData=null; 
    int[] groupIndicator={R.drawable.toright,R.drawable.todown};
    ExpandableListView list=null;
    
    
    
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        groupData=new ArrayList<HashMap<String,Object>>();
        childData=new ArrayList<ArrayList<HashMap<String,Object>>> ();
        
        UserInfo user1=new UserInfo("暗夜之殤","總有一天會尋找到自己的幸福",R.drawable.contact_0,"我的好友");
        UserInfo user2=new UserInfo("街角的幸福","有些事終於想開了",R.drawable.contact_1,"我的好友");
        UserInfo user3=new UserInfo("憤怒的小胖","誰再叫我小胖我跟誰急!",R.drawable.contact_3,"朋友");
        UserInfo user4=new UserInfo("放羊的星星","What ever",R.drawable.contact_2,"陌生人");
        
        addUser(user1);
        addUser(user2);
        addUser(user3);
        addUser(user4);
        
        
        //不能用HashMap的實參賦給Map形參,只能new一個HashMap對象賦給Map的引用!
        MyAdapter adapter=new MyAdapter(this,groupData,R.layout.layout_group,groupFrom,groupTo,childData,R.layout.layout_child,childFrom,childTo );
        
        list=(ExpandableListView)findViewById(R.id.qq_list);
        list.setAdapter(adapter);
        list.setGroupIndicator(null);
        
        
        
    }

    protected void addUser(UserInfo user)
    {
        int i;
        for(i=0; i< groupData.size(); i++){
            if(groupData.get(i).get("groupName").toString().equals(user.groupInfo)){
                break;
            }
        }
        if(i>=groupData.size()){
            HashMap<String,Object> map=new HashMap<String,Object>();
            map.put("groupImage", groupIndicator);
            map.put("groupName",user.groupInfo );
            map.put("childCount", 0);
            groupData.add(map);
            
            ArrayList<HashMap<String,Object>> list=new ArrayList<HashMap<String,Object>>();
            childData.add(list);
        }
        
        HashMap<String,Object> userData=new HashMap<String,Object>();
        userData.put("userImage",user.userImage );
        userData.put("userName", user.userName);
        userData.put("userSign", user.userSign);
        childData.get(i).add(userData);
        Integer count=(Integer)groupData.get(i).get("childCount")+1;
        groupData.get(i).put("childCount", count);    
        
    }
}

 

 有些代碼是為了美化界面用的不必深究。

下面附上效果圖:

幾點總結:
1、在getChildView方法中,要使用inflate()方法,注意該方法的第二個參數一般為null,不用考慮為parent的情況
2、在適配器類中最好不要調用適配器的類方法,那些方法是系統在繪制View時使用的,亂用會導致異常
3、Java語法:可以使用new 方法創建一個普通類(HashMap)賦值給接口類(Map),但普通類對象不能作為實參傳遞給接口類形參。
4、如果想去掉ListView的分割線,必須同時設定
    android:divider="#aaaaaa"   <!--顏色-->
    android:dividerHeight="0px"
前者可以讓分割線變成無邊框的矩形,然后調節成0像素使分割線消失。


免責聲明!

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



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