仿QQ列表--Android控件ExpandableListView的使用

本文介绍如何在Android应用中使用ExpandableListView实现分组可展开列表,包括XML布局文件和Java代码的具体实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用过手机QQ的人都知道,那种可以展开并且合并的想过的确很不错。之前做过列表显示绝大部分都是使用的ListView。虽然可以实现列表的展示,这种方法不是很简单也很繁琐,因此在某些情况下,我们还是希望用到可以分组并实现收缩的列表。值得庆幸的是Android为用户提供了这么一个控件 ExpandableListView。

今天研究了一下这个的用法,也参考了一些资料动手写了一个小demo,实现了基本的功能,但界面优化方面做得还不够好,有待改进。

 http://www.cnblogs.com/over140/archive/2011/03/18/1987666.html 这个中文api不错。

运行结果如图:



首先是activity_main.xml  相对布局中嵌套线性布局

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:background="@drawable/background"
    tools:context=".MainActivity" >

    <LinearLayout
        android:id="@+id/linear"
        android:layout_width="fill_parent"
        android:layout_height="30dp"
        android:orientation="horizontal"
        android:background="#00AAFF" >

        <ImageView
            android:id="@+id/img"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:src="@drawable/img_1" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="USER[在线]" />
    </LinearLayout>

    <ExpandableListView
        android:id="@+id/expandableListView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_below="@id/linear" >
    </ExpandableListView>

</RelativeLayout>


然后需要进行设置的是 listview_group_item.xml 这个是分组菜单的设计,使用相对布局

listview_group_item.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/RelativeLayout1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <ImageView
        android:id="@+id/listview_image"
        android:layout_width="10dp"
        android:layout_height="10dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:src="@drawable/right" />

    <TextView
        android:id="@+id/listview_group_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/listview_image"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@+id/listview_image"
        android:text="分组名称"
        android:textColor="#000000" />

    <TextView
        android:id="@+id/listview_group_num"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="10dp"
        android:text="[10/10]"
        android:textColor="#000000" />

</RelativeLayout>

然后是子菜单里面的布局 listview_child_item.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="40dip" >

    <ImageView
        android:id="@+id/listview_child_img"
        android:layout_width="40dip"
        android:layout_height="40dip"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="10dp"
        android:src="@drawable/img_1" />

    <TextView
        android:id="@+id/listview_child_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/listview_child_img"
        android:text="昵称"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/listview_child_trends"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/listview_child_name"
        android:layout_alignParentBottom="true"
        android:text="该好友暂时没有新动态"
        android:textSize="12sp" />

</RelativeLayout>

接下来 开始进行编写代码。 

MainActivity.java

package com.demo.qqlistpro;

import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.Window;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ExpandableListView.OnGroupCollapseListener;
import android.widget.ExpandableListView.OnGroupExpandListener;
import android.widget.Toast;

public class MainActivity extends Activity {

	ExpandableListView expandableListView = null;

	// 群组名称
	private String[] group = new String[] { "在线好友", "我的好友", "哥们" };
	// 好友名称
	private String[][] users = new String[][] {
			{ "好友1", "好友2", "好友3", "好友4" },
			{ "好友5", "好友6", "好友7", "好友8", "好友9", "好友10", "好友11", "好友12",
					"好友13", "好友14" },
			{ "好友15", "好友16", "好友17", "好友18", "好友19", "好友20" } };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// 设置无标题
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);

		expandableListView = (ExpandableListView) findViewById(R.id.expandableListView);
		// 去除列表前自带的箭头
		expandableListView.setGroupIndicator(null);


		// 配置适配器
		ExpandableListAdapter adapter = new QqAdapter(this, group, users);
		expandableListView.setAdapter(adapter);

		// 设置打开第一组成员(必须在设置适配器之后)
		expandableListView.expandGroup(0);
		// 分组展开
		expandableListView
				.setOnGroupExpandListener(new OnGroupExpandListener() {

					@Override
					public void onGroupExpand(int arg0) {
						Toast.makeText(MainActivity.this, "分组展开",
								Toast.LENGTH_SHORT).show();
					}
				});
		// 分组合并
		expandableListView
				.setOnGroupCollapseListener(new OnGroupCollapseListener() {

					@Override
					public void onGroupCollapse(int arg0) {
						Toast.makeText(MainActivity.this, "分组合并",
								Toast.LENGTH_SHORT).show();

					}
				});
		// 子菜单
		expandableListView.setOnChildClickListener(new OnChildClickListener() {

			@Override
			public boolean onChildClick(ExpandableListView arg0, View arg1,
					int groupPosition, int childPosition, long arg4) {
				new AlertDialog.Builder(MainActivity.this)
						.setIcon(R.drawable.img_1)
						.setMessage(
								group[groupPosition] + " : "
										+ users[groupPosition][childPosition])
						.setTitle("用户信息").show();
				return false;
			}
		});

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}


上段代码中需要配置一个适配器QqAdapter,这里自定义的适配器继承于BaseExpandableListAdapter

详细代码如下

QqAdapter.java

/**
 * 
 */
package com.demo.qqlistpro;

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;

/**
 * @author Administrator
 * 
 */
public class QqAdapter extends BaseExpandableListAdapter {

	private String[] group = null;
	private String[][] users = null;
	private Context context = null;
	private LayoutInflater inflater = null;

	public QqAdapter(Context context, String[] group, String[][] users) {
		this.group = group;
		this.context = context;
		inflater = LayoutInflater.from(context);
		this.users = users;
	}

	/**
	 * 取得子菜单内容
	 */
	@Override
	public Object getChild(int arg0, int arg1) {
		return users[arg0][arg1];
	}

	/**
	 * 取得子菜单ID
	 */
	@Override
	public long getChildId(int arg0, int arg1) {
		return arg1;
	}

	/**
	 * 设置子菜单列表详情
	 */
	@Override
	public View getChildView(int groupPosition, int childPosition,
			boolean arg2, View convertView, ViewGroup arg4) {
		// 配置适配器
		convertView = inflater.inflate(R.layout.listview_child_item, null);
		// 取得组件
		TextView textView = (TextView) convertView
				.findViewById(R.id.listview_child_name);
		// 设置组件内容
		textView.setText(getChild(groupPosition, childPosition).toString());

		return convertView;
	}

	/**
	 * 根据组ID取得子菜单个数
	 */
	@Override
	public int getChildrenCount(int groupPosition) {
		return users[groupPosition].length;
	}

	/**
	 * 取得分组情况
	 */
	@Override
	public Object getGroup(int groupPosition) {
		return group[groupPosition];
	}

	/**
	 * 取得分组个数
	 */
	@Override
	public int getGroupCount() {
		return group.length;
	}

	/**
	 * 取得分组ID
	 */
	@Override
	public long getGroupId(int groupPosition) {
		return groupPosition;
	}

	/**
	 * 设置分组详情
	 */
	@Override
	public View getGroupView(int groupPosition, boolean isExpanded,
			View convertView, ViewGroup arg3) {
		// 配置适配器
		convertView = inflater.inflate(R.layout.listview_group_item, null);
		TextView textView = (TextView) convertView
				.findViewById(R.id.listview_group_name);
		textView.setText(getGroup(groupPosition).toString());
		// 设置每组人数
		TextView tv = (TextView) convertView
				.findViewById(R.id.listview_group_num);
		tv.setText("[" + getChildrenCount(groupPosition) + "/"
				+ getChildrenCount(groupPosition) + "]");
		// 设置图片
		ImageView imageView = (ImageView) convertView
				.findViewById(R.id.listview_image);
		imageView.setImageResource(R.drawable.right);
		// 如果打开菜单
		if (isExpanded) {
			imageView.setImageResource(R.drawable.down);
		}

		return convertView;
	}

	/**
	 * 组和子元素是否持有稳定的ID
	 */
	@Override
	public boolean hasStableIds() {
		return true;
	}

	/**
	 * 子选项是否可以选择
	 */
	@Override
	public boolean isChildSelectable(int arg0, int arg1) {
		// TODO Auto-generated method stub
		return true;
	}

}

由此仿QQ列表已经完成,ExpandableListView得基本使用也基本完成了。运行结果已经在上面贴出。

其中有使用几张图片,可以在网上随便下载几张。名称分别为:background.jpg、down.ico、img_1.ico、right.ico,直接放到res/drawable下即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值