Android UI编程(2)——多级列表(ExpandableListView)

参考博客:

http://blog.csdn.net/xyz_lmn/article/details/6906268

http://www.apkbus.com/android-124715-1-1.html

有时候,使用ListView并不能满足应用程序所需要的功能。有些应用程序需要多组ListViw,这时候我们就要使用一种新的控件ExpandableListView——可以扩展的ListView。它的作用就是将ListView进行分组。就好像我们使用QQ的时候,有"我的好友","陌生人","黑名单"一样,点击一下会扩展开,再点击一下又会收缩回去。ExpandableListView是一个垂直滚动显示两级列表项的视图,与ListView不同的是,它可以有两层:每一层都能够被独立的展开并显示其子项。这些子项来自于与该视图关联的ExpandableListAdapter。

每一个可以扩展的列表项的旁边都有一个指示箭头用来说明列表项目前的状态(这些状态一般是已经展开的列表项,还没有展开的列表项,子列表和最后一个子列表项)。可以使用方法:setChildIndicator(Drawable),setGroupIndicator(Drawable)(或者相应的xml文件属性)去设置这些指示符的样式,当然也可以使用默认的指示符。

和ListView一样,ExpandableListView也是一个需要Adapter作为桥梁来取得数据的控件。一般适用于ExpandableListView的Adapter都要继承BaseExpandableListAdapter这个类,并且必须重载getGroupView和getChildView这两个最为重要的方法。

总结

1、ExpandableListView可扩展列表需要配合BaseExpanableListAdapter的子类来实现,并且实现getGroupView和getChildView两个方法

2、一级列表与二级列举数据集合问题

所以一级列表采用一级集合存储数据,二级列表采用二级集合存储数据,用代码实现如下:

<pre name="code" class="java">ArrayList<String> arrayList_groupData;
ArrayList<ArrayList<String>> arrayList_memberData;
arrayList_groupData = new ArrayList<String>();
arrayList_memberData = new ArrayList<ArrayList<String>>();
for (int i = 0; i < 5; i++)
{
     arrayList_groupData.add("Group "+i);
     ArrayList<String> arrayList_memberDataItem = new ArrayList<String>();
     for (int j = 0; j < 6; j++)
     {
        arrayList_memberDataItem.add("member "+j);
     }
     arrayList_memberData.add(arrayList_memberDataItem);
}

3、在调用expandableListView.setAdapter(exAdapter)的时候,只会调用getGroupView方法(其中expandableListView是ExpandableListView的实例化对象,而exAdapter是继承于BaseExpandableListAdap的类实例对象)。而当一级列表子项被展开,首先会多次调用getGroupView方法,当是被展开的一级列表子项,则调用getChildView方法依次陈列二级列表子项。

4、设置二级列表左侧离一级列表的距离

只需要设置二级列表所对应布局中的第一个控件的android:layout_marginLeft属性,即设置该控件左边离父布局的距离。

5、设置一级列表的高度

将一级列表对应的布局文件所有控件放在一个LinearLayout线性布局中,然后通过设置此LinearLayout线性布局的android:layout_height属性,设置为多少个dip。在此之前我没有把此布局文件放到一个新的LinearLayout线性布局中,因为本身父布局就是LinearLayout线性布局,同样去设置android:layout_height属性值,却不能改变一级列表的高度,只有将所有空间重新放到新的LinearLayout线性布局中并设置android:layout_height属性值才可以,这里有点不明白?

AndroidManifest.xml——没有做任何修改,默认

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.wxl.expandablelistview"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.wxl.expandablelistview.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

string.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name"> 多级列表</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>

</resources>

grouplayout.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="match_parent"
    android:orientation="horizontal">

    <LinearLayout
        android:id="@+id/linearlayout"
        android:layout_width="match_parent"
    	android:layout_height="40dip">
        <ImageView
	        android:id="@+id/grouplayout_imageView_group"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:src="@drawable/user_group"/>
    	<RelativeLayout
	        android:id="@+id/grouplayout_relativeLayout"
	        android:layout_width="match_parent"
	        android:layout_height="match_parent">
	        <TextView
		        android:id="@+id/grouplayout_textView"
		        android:layout_width="wrap_content"
		        android:layout_height="wrap_content"
		        android:text="Group"
		        android:textSize="15sp"
		        android:layout_marginTop="5dp" />
	    	<ImageView
		        android:id="@+id/grouplayout_imageView_tubiao"
		        android:layout_width="wrap_content"
		        android:layout_height="wrap_content"
		        android:background="@drawable/btn_browser"
		        android:layout_alignParentRight="true"/>
    	</RelativeLayout>
    </LinearLayout>

</LinearLayout>

memberlayout.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="match_parent"
    android:orientation="horizontal"
    android:gravity="center_vertical">

    <ImageView
        android:id="@+id/memberlayout_imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/child_image"
        android:layout_marginLeft="15dp"/>
    <TextView
        android:id="@+id/memberlayout_textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="member"
        android:textSize="20sp"/>

</LinearLayout>

activity_main.xml

<LinearLayout 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"
    tools:context=".MainActivity" >

    <ExpandableListView
        android:id="@+id/expandableListView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:background="@drawable/default_bg"></ExpandableListView>
</LinearLayout>

MainActivity.java

package com.wxl.expandablelistview;

import java.util.ArrayList;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ImageView;
import android.widget.TextView;
import android.app.Activity;
import android.content.Context;

public class MainActivity extends Activity {
	ExpandableListView expandableListView;
	ArrayList<String> arrayList_groupData;
	ArrayList<ArrayList<String>> arrayList_memberData;
	ExAdapter exAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        expandableListView = (ExpandableListView)this.findViewById(R.id.expandableListView);
        arrayList_groupData = new ArrayList<String>();
        arrayList_memberData = new ArrayList<ArrayList<String>>();
        for (int i = 0; i < 5; i++)
        {
        	arrayList_groupData.add("Group "+i);
        	ArrayList<String> arrayList_memberDataItem = new ArrayList<String>();
        	for (int j = 0; j < 6; j++)
        	{
        		arrayList_memberDataItem.add("member "+j);
        	}
        	arrayList_memberData.add(arrayList_memberDataItem);
        }

        exAdapter = new ExAdapter(this);
        expandableListView.setAdapter(exAdapter);
        //expandableListView.expandGroup(0);//设置第一组张开
        //expandableListView.collapseGroup(0); 将第group组收起
        expandableListView.setGroupIndicator(null);//除去自带的箭头,自带的箭头在父列表的最左边,不展开向下,展开向上
        expandableListView.setDivider(null);//这个是设定每个Group之间的分割线。,默认有分割线,设置null没有分割线

        expandableListView.setOnChildClickListener(new OnChildClickListener() {

			@Override
			public boolean onChildClick(ExpandableListView parent, View view, int groupPosition,
					int childPosition, long id) {
				// TODO Auto-generated method stub
				exAdapter.setChildSelection(groupPosition,childPosition);
				exAdapter.notifyDataSetChanged();
				return true;
			}
		});
    }

    public class ExAdapter extends BaseExpandableListAdapter
    {
    	Context context;
    	int selectParentItem = -1;
    	int selectChildItem = -1;

    	public ExAdapter(Context context) {
			// TODO Auto-generated constructor stub
    		this.context = context;
		}

    	public void setChildSelection(int groupPosition, int childPosition)
    	{
    		selectParentItem = groupPosition;
    		selectChildItem = childPosition;
    	}

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

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

		@Override
		public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
				ViewGroup parent) {
			// TODO Auto-generated method stub
			View view = convertView;
			Log.i("++++++++++", "groupPosition="+groupPosition+","+"childPosition"+childPosition);
			if (null == view)
			{
				//获取LayoutInflater
				LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				//获取对应的布局
				view = layoutInflater.inflate(R.layout.memberlayout, null);
			}
			TextView textView = (TextView)view.findViewById(R.id.memberlayout_textView);
			textView.setText(arrayList_memberData.get(groupPosition).get(childPosition));
			if (selectChildItem == childPosition && selectParentItem == groupPosition)
			{
				Log.i("++++++++++", "点击:"+groupPosition+","+childPosition);
			}

			return view;
		}

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

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

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

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

		@Override
		public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
				ViewGroup parent) {
			// TODO Auto-generated method stub
			View view = convertView;
			Log.i("++++++++++", "groupPosition="+groupPosition);
			if (null == view)
			{
				LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				view = layoutInflater.inflate(R.layout.grouplayout, null);
			}
			TextView textView = (TextView)view.findViewById(R.id.grouplayout_textView);
			textView.setText(arrayList_groupData.get(groupPosition));
			ImageView image=(ImageView) view.findViewById(R.id.grouplayout_imageView_tubiao);
			if(isExpanded)
			{
				image.setBackgroundResource(R.drawable.btn_browser2);
			}
			else
			{
				image.setBackgroundResource(R.drawable.btn_browser);
			}
			return view;
		}

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

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

    }

}

时间: 2024-08-27 20:36:23

Android UI编程(2)——多级列表(ExpandableListView)的相关文章

Android UI编程之自定义控件初步——ImageButton

概述: 我想我们在使用一些App的时候,应该不会出现一些"裸控件"的吧.除非是一些系统中的软件,那是为了保持风格的一致性,做出的一些权衡.我这里并非是在指责Android原生的控件不好看,说实在的,我很喜欢Android的一些原生控件.只是有些时候为了风格的一致性,就不得不去花些功夫在美工上.这于美工这一点,我对某讯的产品的确欣赏.下面就让我们开始一点一点学习Android UI编程中的自定义控件. 分析: 自定义控件就点像堆积木,并给它涂上颜色,和功能说明.下面就让我们用一个例子来逐

Android UI编程之自定义控件初步(下)——CustomEditText

概述: 基于对上一篇博客<Android UI编程之自定义控件初步(上)--ImageButton>的学习,我们对自定义控件也有了一个初步的认识.那现在我们可以再试着对EditText进行一些自定义的学习.以下有两种方式的自定义UI编程分享给大家. 示例:带删除按钮的输入框 效果图展示:   基本雏形搭建: 大家可以从上面的效果图上看到两个东西:左侧的EditText和右侧的图片(这里是一个Button).我们在EditText中的输入为空的时候,不显示右侧的清除按钮.一旦EditText中输

Android UI编程(6)——HandlerThread

介绍: HandlerThread继承Thread,当线程开启时,也就是它run方法运行起来后,线程同时创建了一个含有消息队列的Looper,并对外提供自己这个Looper对象的get方法,这就是它和普通Thread唯一不同的地方. 好处: 为什么要使用HandlerThread 1.开发中如果多次使用类似new Thread(){}.start(); 这种方式开启一个子线程,会创建多个匿名线程,使得程序运行越来越慢,而HandlerThread自带Looper使他可以通过消息来多次重复使用当前

Android UI编程(4)——Thread、Message、Handler

当应用程序启动时,会开启一个主线程(也就是UI线程),由它来管理UI,监听用户点击,来响应用户并分发事件等.所有一般在主线程中不要执行比较耗时的操作,如延时.下载网络数据.死循环,否则出现ANR错误.所以就将这些操作放在子线程中,但是由于Android UI线程是不安全的,所有只能在主线程中更新UI.使用Thread来创建子线程.使用Message来存储数据.使用Handler来处理消息数据. 总结: 1.子线程与UI主线程之间通过Message来传递数据,需要创建一个新类(MyHandler)

Android UI编程(7)——Fragment

Fragment是Activity的界面中的一部分或一种行为.你可以把多个Fragment们组合到一个Activity中来创建一个多面界面并且可以在多个Activity中重用一个Fragment.也可以把Fragment认为模块化的一段Activity,它具有自己的生命周期,接收它自己的事件,并可以在Activity运行时被添加或删除. Fragment不能独立存在,它必须嵌入到activity中,而且Fragment的生命周期直接受所在的Activity的影响.例如:当Activity暂停时,

Android UI编程(1)——九宫格(GridView)

参考博客:http://blog.csdn.net/xyz_lmn/article/details/6906255 总结: 1.GridView(网格视图)按照行列来显示内容,每个网格可以用已有的布局或自定义的布局来填充,并且GridView每行可以显示多个网格,即有列数之说. 2.GridView需要结合适配器(Adapter)一起使用,使用GridView类的实例对象中的setAdapter方法初始化网格视图,即gridView.setAdapter(myAdapter). 3.将GridV

Android UI编程(5)——Looper

Looper通常是运行在一个消息的循环队列中的这个线程中,线程默认不会提供一个循环的消息去关联它们,即在一般的线程中是没有一个消息队列去关联这个消息的.那么如果线程想管理这些消息,就必须在此线程中调用Looper.prepare()使这个消息队列运行起来,并且调用Looper.loop()这个方法使它消息队列一直运行到停止.而Handler就是消息队列一个交互消息,包括从将消息发到消息队列,以及从消息队列取出消息并处理. 总结: Android使用Message对象来管理消息数据,并将这些Mes

Android UI编程(9)——ViewPager、Activity

利用ViewPager可以实现滑屏效果,如今智能手机随处可见滑屏效果.最常见的就是手机launcher上的滑屏,以及各大型软件个菜单之间的滑屏,如微信. 参考博客:http://blog.csdn.net/harvic880925/article/details/38521865,里面有对ViewPager详细讲解 先看效果图: 代码: AndroidManifest.xml--没有做任何修改,创建工程默认 <?xml version="1.0" encoding="u

Android UI编程(View、ViewGroup类、按钮、TextView、EditText)

1.View和ViewGroup类 Android中所有的UI元素都是使用View和ViewGroup类的对象建立的. View:将一些信息绘制在屏幕上可以与用户产生交互 Viewgroup:包含多个View和Viewgroup的容器,用来定义UI布局 2.按钮 (1)方式一: 配置: <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height=