zoukankan      html  css  js  c++  java
  • 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像素使分割线消失。

  • 相关阅读:
    PHP读取excel中地址实现多文件下载
    PHP中域名绑定
    js生成word中图片处理
    Mysql查询不为null值
    Specified key was too long max key length is 1000 bytes
    无法向Windows服务器复制粘贴文件
    Sql Server Configuration Manager 网络配置为空,没有实例
    The first one
    前端基本知识 防抖、节流,compose 函数,apply,bind,call
    写一个闭包 ,每次调用都加1
  • 原文地址:https://www.cnblogs.com/carlos-vic/p/Carlos_V_Android_9.html
Copyright © 2011-2022 走看看