【Android基础篇】使用ExpandableListView实现自定义的下拉列表

1. ExpandableListView简介

下拉列表(可扩展的列表控件)在App应用非常常见,在Android开发中是我们必须掌握的一个控件,下面就来介绍一下ExpandableListView这个控件的开发。

ExpandableListView分为组列表项和子列表项,单击组列表项,会显示这组里所有的子列表项。和ListView一样,它也是通过Adapter数据适配器完成数据与显示的衔接,但它使用的另一种接口:ExpandableListAdapter.

今天我们要做的是实现一个继承它的父接口:BaseExpandableListAdapter的类,来实现自定义的下拉列表(就是如同ListView里的方式,给它的列表项设置界面布局文件layout)。

2. 示例

示例包含四个文件,两个Java文件和两个layout文件。Java文件包含一个Activity,和我们自己实现的MyExpandAdapter;layout文件一个是用于Activity,另一个就是子列表项的界面布局文件,至于组列表项的布局,我们通过直接在代码里创建一个TextView来实现,这样,就同时介绍了下拉列表样式实现的两种方法。

plan_manager.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ExpandableListView
        android:id="@+id/expandableListView_plan_manager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ExpandableListView>

</LinearLayout>

布局文件,添加控件

PlanManager.java

package com.plan;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ExpandableListView;
import android.widget.Toast;

import com.example.plan.R;

public class PlanManager extends Activity{

    ExpandableListView sp_date_list = null;     //列表
    MyExpandAdapter adapter = null;             //数据适配器

    List<String> group_head;                    //组列表项,每个组都有一个子List
    List<List<String>> child;                   //子列表项

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.plan_manger);
        //获取控件
        sp_date_list = (ExpandableListView)findViewById(R.id.expandableListView_plan_manager);
        //初始化组、子列表项
        group_head = new ArrayList<String>();
        child = new ArrayList<List<String>>();

        //设置适配器
        sp_date_list.setAdapter(new MyExpandAdapter(this,group_head,child)); //设置数据适配器
        sp_date_list.setCacheColorHint(0);              //拖动列表的时候不出现黑色背景

        addGroup("静夜思");
        addGroup("春晓");
        addChild(0,"床前明月光");
        addChild(0,"疑是地上霜");
        addChild(1,"春眠不觉晓");
        addChild(1,"处处闻啼鸟");
    }

    //添加组列表项
    public void addGroup(String group){
        group_head.add(group);
        child.add(new ArrayList<String>()); //child中添加新数组
    }

    //添加对应组的自列表项
    public void addChild(int position,String child){
        List<String> it = this.child.get(position);
        if(it != null){
            it.add(child);
        }else{
            it = new ArrayList<String>();
            it.add(child);
        }
    }

    //子列表项被选中的响应方法
    public void childSelect(int groupPosition,int childPosition){
        Toast.makeText(getBaseContext(), Integer.toString(groupPosition)+":" +
                Integer.toString(childPosition), 2000).show();
    }

}

查找控件,连接显示与适配器,并添加一些示例数据,其中的addGroup和addChild以及childSelect可以提供给其他组件作为接口

plain_text.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <TextView
        android:id="@+id/textView_plain_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView" />

</LinearLayout>

这是子列表项的布局文件,因为只是简单示例,太复杂了的话学起来麻烦,所以只用了一个文本框,在实际项目中可以多加几个控件,改一下child的类型(最好改成map映射)就好

MyExpandAdapter.java

package com.plan;

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

import android.content.Context;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;

import com.example.plan.R;

public class MyExpandAdapter extends BaseExpandableListAdapter{

    List<String> group_head;
    List<List<String>> child;
    PlanManager context;

    public MyExpandAdapter(Context content){
        //初始化组、子列表项
        group_head = new ArrayList<String>();
        child = new ArrayList<List<String>>();
    }

    public MyExpandAdapter(PlanManager context,List<String> group_head,
    List<List<String>> child){
        this.context = context;
        //初始化组、子列表项
        this.group_head = group_head;
        this.child = child;
    }

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

    @Override
    public int getChildrenCount(int position) {
        // TODO Auto-generated method stub
        if(position<0||position>=this.child.size())
            return 0;
        return child.get(position).size();
    }

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

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        // TODO Auto-generated method stub
        return child.get(childPosition).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 true;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,
            View convertView, ViewGroup parent) {
        //获取文本
        String text = group_head.get(groupPosition);
        if(convertView == null){
            //组列表界面只有一个文本框,直接生成
            convertView = new TextView(context);
            //设定界面,AbsListView:用于实现条目的虚拟列表的基类
            AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
                    ViewGroup.LayoutParams.FILL_PARENT, 60);
            ((TextView) convertView).setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); //文本框放在中央
            convertView.setPadding(45, 0, 0, 0);                               //设置文本里那个下拉的图标远一点
            convertView.setLayoutParams(lp);
            Log.d("Group", text);
        }
        ((TextView) convertView).setText(text);
        return convertView;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {
        //子列表控件通过界面文件设计
        if(convertView ==null){//convert在运行中会重用,如果不为空,则表明不用重新获取
            LayoutInflater layoutInflater;//使用这个来载入界面
            layoutInflater = LayoutInflater.from(context);
            convertView = layoutInflater.inflate(R.layout.plain_text, null);
        }
        TextView tv = (TextView)convertView.findViewById(R.id.textView_plain_text);
        String text = child.get(groupPosition).get(childPosition);
        tv.setText(text);
        //获取文本控件,并设置值
        return convertView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        //调用Activity里的ChildSelect方法
        context.childSelect(groupPosition,childPosition);
        return true;
    }
}

继承接口后,Eclipse可以自动生成这些方法,我们只需要改一下就好。里面有些地方用到了Log.d方法,用于在logcat里输出日志(也可用System.out.println),主要是用来优化一下程序,通过看日志打印了几次,就可以看出程序中的方法是否有被重复调用。

时间: 2024-10-24 00:18:03

【Android基础篇】使用ExpandableListView实现自定义的下拉列表的相关文章

android基础篇学习心得

android技术中,线程.进程.JNI.IPC和各个小框架结构是基本功.在跟随高焕堂老师的android程序猿到架构师之路系列视频中 学习完基础篇之后,颇有些心得,记录下来. android开发就是app开发吗?曾听过很多人说android学习很简单,做个app轻松就上手了.我一直觉得不以为然,许多程序员做app开发时,心中大致只有四大组件.各种布局.数据库和一些常用控件.对于各小框架.线程间通信.绑定服务.java与c的对接等基本原理并不清楚,也没必要弄清楚. 最近学校搞了一个实训,要求做一

【android基础篇】自定义广播和电话监听

I,自定义广播 前面所说的都是接收短信,外拨电话等都是系统所有的广播,而其实我们可以自己自定义一个广播,并且写一个广播接收者来玩玩. 1) 在按钮的点击方法中,发送自定义的广播: 1 public void click(View view){ 2 /** 3 * 发送自定义的广播 4 */ 5 Intent intent=new Intent(); 6 //设置意图的动作,要和自定义的频道要一致 7 intent.setAction("www.wangchengxiang.com");

【Android基础篇】AutoCompleteTextView和MultiAutoCompleteTextView

从名称上可看出来,这两个控件都是用于输入信息的TextView,AutoComplete已表明这两个控件内容输入都是自动完成的.区别在于一个是Multi,一个不是,具体的区别可通过下面的内容看出来.下面分别介绍着两个控件的使用. AutoCompleteTextView 功能 动态匹配输入的内容,如搜索引擎在输入框输入信息时,会有一个下拉列表显示与当前输入内容有关的信息. 控件特有属性 如同width.height等属性是控件共有属性,下面介绍AutoCompleteTextView特有的属性:

Android基础控件——ImageView的自定义,巧用Matrix实现图片不变形的炫酷PK条

前言 在开发中常常会遇到PK条制作,如果在PK条中是纯色的情况下,比较好办,如下:我们通常会设置其权重进行更新两个PK条的进度,实现起来也简单 //更新PkBar宽度比例 private void updateLayoutParams(float ratio) { LinearLayout.LayoutParams paramsLeft = (LinearLayout.LayoutParams) mLeftBar.getLayoutParams(); LinearLayout.LayoutPar

从0开始不断温习,Android基础篇

(^▽^)经常发现学着学着,由于学习的东西越来越多,接触的东西越来越多,逐渐的吧自己的最基础的东西忘得差不多了(o(╥﹏╥)o我也差不多忘了很多东西了)发现越优秀的人 越注重细节,基础更加扎实和巩固 分享一下自己整理的面试学习路线 请查看完整的PDF版(更多完整项目下载.未完待续.源码.图文知识后续上传github.)可以点击关于我联系我获取完整PDF(VX:mm14525201314) 一.Activity 是什么? Activity 实际上只是一个与用户交互的接口而已 二.Activity

【android基础篇】自定义控件实现一些比较常见的功能

I,我要实现的效果 如图所示: 当下拉时,显示下拉刷新.松开后,显示松开刷新,接着正在刷新. II,准备工作 1)需要自定义ListView,写一个类继承ListView.并在ListView中添加一些数据. 1 private void initView() { 2 listData = new ArrayList<String>(); 3 for (int i = 0; i <30; i++) { 4 listData.add("我是来自仙桃的西藏哥,我真的很爱骑行....

Android 基础篇(二)

ADB进程 adb指令 adb install xxx.apk adb uninstall 包名 adb devices adb start-server adb kill-server adb shell –> 进入Linux的命令行 ls –> 显示文件及包名 ps –> 列举所有运行的进程 rm –> 删除文件 cd –> 切换目录 adb push 文件路径/文件名 sdcard/文件名 –> 把文件放进去 adb pull sdcard/文件名 –> 把

ios基础篇(九)——自定义UITabBar

上一篇讲到了UITabBarViewController,接着说说UITabBarViewController中怎么自定义TabBar. 今天仿写了微博,发现底部tabbar中间的button和其他有所不同,button较大且着色:而且我们平时工作中也有很多类似这样的问题,有些app有一个看起来像标准 tabBarController,但是呢,tabBar的中间是凸起的或者着色的.我们怎样做可以构建这种现实效果呢? 如图: 这些标签栏除了中间项以外看起来都相当的标准,所以我们会从一个标准的包含一

Android基础篇之Android快速入门--你必须要知道的基础

Android快速入门 1. 搭建开发环境 >解压压缩文件,得到:①Android SDK   (类似于JDK)② Eclipse  ③ADT >配置两个path环境变量:D:\adt-bundle-windows-x86\sdk\platform-tools:D:\adt-bundle-windows-x86\sdk\tools >配置基本的Eclipse的设置: 调整字体大小,字符集,配置android sdk的位置 >创建模拟器: 2. 创建第一个Android项目: Hel