Android编程应用--仿QQ我的好友ExpandableListView应用

简介:

QQ好友界面利用ExpandableListView显示分组和好友列表,以及分组的点击实现对好友列表的显示。
开发中需要类似布局,将源码和解析探讨如下:

效果图:


实现方式:

S1 写ExpandableListView的布局XML文件

非常简单,只需要ExpandableListView控件即可

写上必要的ID(为了获取控件),设置好背景色,间距色

<?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="match_parent"
    android:orientation="vertical" >
    
    <ExpandableListView 
        android:id="@+id/personInfoListView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@color/home_item_normal"
        android:divider="@color/home_item"
        android:dividerHeight="1px" >
    </ExpandableListView>

</LinearLayout>
布局效果如下所示:


S2 写父ITEM具体布局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="?android:attr/listPreferredItemHeight"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/group_name"
        android:layout_width="wrap_content"
        android:layout_height="45dip"
        android:layout_marginLeft="35dip"
        android:gravity="center_vertical"
        android:singleLine="true"
        android:text="test"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="@color/home_item"
        android:textSize="16sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/group_count"
        android:layout_width="wrap_content"
        android:layout_height="45dip"
        android:layout_marginLeft="5dip"
        android:gravity="center_vertical"
        android:singleLine="true"
        android:text="test"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="@color/home_item"
        android:textSize="16sp"
        android:textStyle="bold" />

</LinearLayout>
显示效果如图:


S3 写子ITEM具体布局XML

显示每个用户图标、用户名称、用户个性签名
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:minHeight="64dip"
    android:descendantFocusability="blocksDescendants"
    android:orientation="horizontal" >

    <ImageButton
        android:id="@+id/img"
        android:layout_width="60dip"
        android:layout_height="60dip"
        android:layout_marginLeft="2dip"
        android:layout_marginRight="10dip"
        android:layout_gravity="center_vertical" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:descendantFocusability="blocksDescendants"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/item_name"
            android:layout_width="wrap_content"
            android:layout_height="0.0dip"
            android:gravity="center_vertical"
        	android:text="test"
        	android:textSize="15.0sp"
        	android:textColor="#ffc21513"
        	android:textStyle="bold"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/item_detail"
            android:layout_width="wrap_content"
            android:layout_height="0.0dip"
            android:gravity="center_vertical"
            android:singleLine="true"
            android:ellipsize="end"
        	android:textSize="15.0sp"
        	android:textColor="#ff666666"
        	android:textStyle="bold"
        	android:text="test"
            android:layout_weight="1" />
        
    </LinearLayout>

</LinearLayout>
显示效果如图:

S4 编写用于用户显示的对应实体类

存储每个人的信息进行封装

package com.rxz.util;

public class PersonListItem {
	
	// 图片资源
	private int resId;
	// 姓名
	private String name;
	// 个性签名
	private String detail;

	public PersonListItem(int resId, String name, String detail) {
		this.resId = resId;
		this.name = name;
		this.detail = detail;
	}

	public void setImageId(int resId) {
		this.resId = resId;
	}

	public int getImageId() {
		return resId;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setDetail(String detail) {
		this.detail = detail;
	}

	public String getDetail() {
		return detail;
	}

	public String toString() {
		return "Item[" + resId + ", " + name + ", " + detail + "]";
	}
}
简单说就是一个基本的JavaBean,包括基本属性和相应的Getter,Setter和构造函数

S5 编写自定义ExpandableListView适配器

关于什么是适配器请自行Google,简单说就是一个 ListView 的功能接口
package com.rxz.util;

import java.util.List;

import com.rxz.expandablelistdemo.R;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MyAdapter extends BaseExpandableListAdapter{

	private Context mContext = null;
    private LayoutInflater mInflater = null;
    private List<String>   mGroupStrings = null;
    private List<List<PersonListItem>>   mData = null;

    /**
     * 构造函数
     * @param mContext
     * @param mGroupStrings
     * @param mData
     */
	public MyAdapter(Context mContext, List<String> mGroupStrings,
			List<List<PersonListItem>> mData) {
		super();
		this.mContext = mContext;
		this.mGroupStrings = mGroupStrings;
		this.mData = mData;
		this.mInflater = (LayoutInflater) this.mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	}

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

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

	@Override
	public List<PersonListItem> getGroup(int groupPosition) {
		// TODO Auto-generated method stub
		return mData.get(groupPosition);
	}

	@Override
	public PersonListItem getChild(int groupPosition, int childPosition) {
		// TODO Auto-generated method stub
		return mData.get(groupPosition).get(childPosition);
	}

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

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

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

	/**
	 * 获取父视图,当父视图被加载时调用
	 */
	@Override
	public View getGroupView(int groupPosition, boolean isExpanded,
			View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		if (convertView == null) {
            convertView = mInflater.inflate(R.layout.person_group_item_layout, null);
        }
        GroupViewHolder holder = new GroupViewHolder();
        // 组名
        holder.mGroupName = (TextView) convertView.findViewById(R.id.group_name);
        holder.mGroupName.setText(mGroupStrings.get(groupPosition));
        // 组内人数
        holder.mGroupCount = (TextView) convertView.findViewById(R.id.group_count);
        holder.mGroupCount.setText("[" + mData.get(groupPosition).size() + "]");
        return convertView;
	}

	/**
	 * 获取子视图,当子视图加载时会调用
	 */
	@Override
	public View getChildView(int groupPosition, int childPosition,
			boolean isLastChild, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		if (convertView == null) {
            convertView = mInflater.inflate(R.layout.person_child_item_layout, null);
        }
        ChildViewHolder holder = new ChildViewHolder();
        // 图标
        holder.mIcon = (ImageView) convertView.findViewById(R.id.img);
        holder.mIcon.setBackgroundResource(getChild(groupPosition, childPosition).getImageId());
        // 用户名
        holder.mChildName = (TextView) convertView.findViewById(R.id.item_name);
        holder.mChildName.setText(getChild(groupPosition, childPosition).getName());
        // 签名
        holder.mDetail = (TextView) convertView.findViewById(R.id.item_detail);
        holder.mDetail.setText(getChild(groupPosition, childPosition).getDetail());
        return convertView;
	}

	@Override
	public boolean isChildSelectable(int groupPosition, int childPosition) {
		// TODO Auto-generated method stub
		return true;
	}
	
	/**
	 * ViewHolder
	 * 将控件封装方便操作
	 * @author Mr-rxz
	 *
	 */
	private class GroupViewHolder {
		// 显示组名
        TextView mGroupName;
        // 显示组内成员数量
        TextView mGroupCount;
    }

    private class ChildViewHolder {
    	// 图标
        ImageView mIcon;
        // 用户名
        TextView mChildName;
        // 签名
        TextView mDetail;
    }

}

S6 最后就是编写界面层Activity了

这里加载了一些假数据,并对用户点击事件做了简单的删除操作
package com.rxz.activity;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.Toast;

import com.rxz.expandablelistdemo.R;
import com.rxz.util.MyAdapter;
import com.rxz.util.PersonListItem;

public class ActivityMain extends Activity implements OnChildClickListener {

	private ExpandableListView mListView = null;
	// 表格适配器
	private MyAdapter mAdapter = null;
	// 组内好友
	private List<List<PersonListItem>> mData = new ArrayList<List<PersonListItem>>();
	// 分组名字
	private List<String> GroupName = new ArrayList<String>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		// 初始化数据
		modifyData();
		// 隐藏标题栏
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		// 加载布局
		setContentView(R.layout.main_activity);
		// 获取控件
		mListView = (ExpandableListView) findViewById(R.id.personInfoListView);
		// 绑定监听事件
		mListView.setOnChildClickListener(this);
		// 设置 Item 格式
		mListView.setGroupIndicator(getResources().getDrawable(
				R.drawable.expander_floder));
		// 设置 ListView点击适配器
		mAdapter = new MyAdapter(this.getApplicationContext(), GroupName, mData);
		mListView.setAdapter(mAdapter);
		mListView
				.setDescendantFocusability(ExpandableListView.FOCUS_AFTER_DESCENDANTS);
	}

	/**
	 * 虚拟数据
	 */
	private void modifyData() {
		GroupName.add("我的好友");
		GroupName.add("陌生人");
		GroupName.add("黑名单");

		List<PersonListItem> itemList = new ArrayList<PersonListItem>();
		itemList.add(new PersonListItem(R.drawable.head_pic1, "贝贝", "北京我愛你"));
		itemList.add(new PersonListItem(R.drawable.head_pic2, "晶晶", "水晶之淚"));
		itemList.add(new PersonListItem(R.drawable.head_pic3, "欢欢", "開開心心每一天"));
		itemList.add(new PersonListItem(R.drawable.head_pic4, "盈盈", "Welcome"));
		itemList.add(new PersonListItem(R.drawable.head_pic5, "妮妮", "嘿嘿"));
		mData.add(itemList);
		
		List<PersonListItem> itemList2 = new ArrayList<PersonListItem>();
		itemList2.add(new PersonListItem(R.drawable.head_pic6, "呵呵", "我恨你"));
		mData.add(itemList2);
		
		List<PersonListItem> itemList3 = new ArrayList<PersonListItem>();
		mData.add(itemList3);
	}

	@Override
	public boolean onChildClick(ExpandableListView parent, View v,
			final int groupPosition, final int childPosition, long id) {
		// TODO Auto-generated method stub
		PersonListItem item = mAdapter.getChild(groupPosition, childPosition);
		new AlertDialog.Builder(this)
				.setTitle(item.getName())
				.setMessage(item.getDetail())
				.setIcon(android.R.drawable.ic_menu_more)
				.setPositiveButton("删除好友", new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						// TODO Auto-generated method stub
						mData.get(groupPosition).remove(childPosition);
						mAdapter.notifyDataSetChanged();
						Toast.makeText(ActivityMain.this, "成功删除该数据",
								Toast.LENGTH_SHORT).show();
					}
				})
				.setNeutralButton("查看详情", new OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						// TODO Auto-generated method stub
						Toast.makeText(ActivityMain.this, "正在查看详情",
								Toast.LENGTH_SHORT).show();
					}
				})
				.setNegativeButton(android.R.string.cancel,
						new OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog,
									int which) {
								// TODO Auto-generated method stub

							}
						}).create().show();
		return true;
	}

}

再简单加一些界面美化...这些不是重点,略过

S7 点击运行,大功告成







如有任何疑问,欢迎留言!

源码公布如下:

源码:http://download.youkuaiyun.com/detail/hit_rxz/7997853

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值