ListView是Android开发中比较常用的一个组件,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示。比如说我们手机里的通讯录就使用到了ListView显示联系人信息。ListView同时也是所有Android UI控件中最为麻烦的控件,之所以麻烦就是因为它的各种的适配器特别麻烦。

创建ListView有两种方式:

1、直接创建ListView

2、让Activity继承ListActivity

列表的显示需要三个元素:

1.ListVeiw :用来展示列表的View。

2.适配器 :用来把数据映射到ListView上的中介。

3.数据集   :具体的将被映射的字符串,图片,或者基本组件。

根据列表的适配器类型,列表分为四种,ArrayAdapter、SimpleAdapter、SimpleCursorAdapter以及自定义Adapter。

其中以ArrayAdapter最为简单,只能展示一行字。SimpleAdapter有最好的扩充性,可以自定义出各种效果。 SimpleCursorAdapter可以认为是SimpleAdapter对数据库的简单结合,可以方面的把数据库的内容以列表的形式展示出来。

下面我们就通过几个简单的例子讲解一下通过各种适配器来构建ListView。

1、1使用ArrayAdatpter构建ListView

新建一个Android项目:ListViewDemo,同时新建一个类ListViewDemoActivity继承Activity,代码如下:package com.liuzhichao.listview;

import android.app.Activity;

import android.os.Bundle;

import android.widget.ArrayAdapter;

import android.widget.ListView;

public class ListViewDemoActivity extends Activity {

//定义一个ListView

private ListView mListView;

//定义一个String数组,数组里的数据就是ListView里的一项

private String[] items={"1、ArrayAdapter_List","2、SimpleAdapter_List"

,"3、SimpleCursorAdapter_List","4、MyAdapter_List"};

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//new一个ListView

mListView = new ListView(this);

//通过setAdapter构建一个ArrayAdapter将items与mListView"绑定"

mListView.setAdapter(new ArrayAdapter(this,

android.R.layout.simple_list_item_1, items));

//显示mListView

setContentView(mListView);

}

}

上面代码使用了ArrayAdapter(Context context, int textViewResourceId, List objects)来装配数据,要装配这些数据就需要一个连接ListView视图对象和数组数据的适配器来两者的适配工作,ArrayAdapter的构造需要三个参数,依次为this,布局文件(注意这里的布局文件描述的是列表的每一行的布局,android.R.layout.simple_list_item_1是系统定义好的布局文件只显示一行文字,数据源(一个List集合)。同时用setAdapter()完成适配的最后工作。运行后的现实结构如下图:

1、2使用SimpleAdapter构建ListView

使用simpleAdapter的数据用一般都是HashMap构成的List,list的每一节对应ListView的每一行。HashMap的每个键值数据映射到布局文件中对应id的组件上。下面我们使用SimpleAdapter模拟一个通讯录。

因为系统没有对应的布局文件可用,我们可以自己定义一个布局info.xml:<?xml version="1.0" encoding="utf-8"?>

android:layout_width="fill_parent"

android:layout_height="fill_parent" >

android:id="@+id/info_img"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="3dp"

android:src="@drawable/ic_launcher"/>

android:id="@+id/info_name"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_toRightOf="@id/info_img"

android:layout_marginTop="5dp"/>

android:id="@+id/info_phone"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_below="@id/info_name"

android:layout_toRightOf="@id/info_img"

android:layout_alignBaseline="@id/info_img"/>

android:id="@+id/info_region"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_toRightOf="@id/info_phone"

android:layout_alignBaseline="@id/info_phone"

android:layout_marginLeft="10dip"/>

新建一个SimpleAdapterListView继续Activity,代码如下:package com.liuzhichao.listview;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.Map;

import android.app.Activity;

import android.os.Bundle;

import android.widget.ListView;

import android.widget.SimpleAdapter;

public class SimpleAdapterListView extends Activity{

//分别定义通讯录中的用户名、电话、地区等信息

private String[] info_Names={"史珍香","赖月京","秦寿生","刘产","扬伟","范剑"};

private String[] info_Phones={"13844445144","13844444444","13444445144","13544445144","13644445144","13744445144"};

private String[] info_Regions={"火星","水星","木星","月球","美国","未知地区"};

//定义一个ArrayList数组,每一条数据对应通讯录中的一个联系人信息

private ArrayList> mInfos= new ArrayList>();

//定义一个ListView

private ListView mListView;

@Override

protected void onCreate(Bundle savedInstanceState) {

// TODO Auto-generated method stub

super.onCreate(savedInstanceState);

//new一个ListView

mListView = new ListView(this);

//添加联系人信息

for(int i=0;i

Map item = new HashMap();

item.put("img", R.drawable.contact_img);

item.put("name", info_Names[i]);

item.put("phone", info_Phones[i]);

item.put("region", info_Regions[i]);

mInfos.add(item);

}

//定义一个SimpleAdapter

SimpleAdapter adapter = new SimpleAdapter(this, mInfos, R.layout.info,

new String[]{"img","name","phone","region"},

new int[]{R.id.info_img,R.id.info_name,R.id.info_phone,R.id.info_region});

//设置mListView的适配器为adapter

mListView.setAdapter(adapter);

setContentView(mListView);

}

}

使用simpleAdapter的数据用一般都是HashMap构成的List,list的每一节对应ListView的每一行。HashMap的每个键 值数据映射到布局文件中对应id的组件上。因为系统没有对应的布局文件可用,我们可以自己定义一个布局info.xml。运行效果如下图:

我相信肯定有人对new SimpleAdapter()中的参数有一些疑问,下面我们就来看一下SimpleAdapter的构造函数:SimpleAdapter(Context context, List extends Map > data, int resource, String[] from, int[] to) ,context相信不用解释了,假设将SimpleAdapter用于ListView。那么ListView的每一个列表项就是resource参数值指定的布局。而data参数就是要加载到ListView中的数据。那么from和to呢?在加载列表项时,需要通过组件的id和data参数中List元素中的Map对象对应。因此,from参数为Map对象的key,而to表示组件的id,例如,本例中的参数值为from=new String[]{“img”,”name”,”phone”,”region”},to=new int[]{R.id.info_img,R.id.info_name,R.id.info_phone,R.id.info_region}),意思就是将Map对象中key为”img”的value绑定到R.id.info_img,将Map对象中key为”name”的value绑定到R.id.info_name,phone、region也类似。所以from和to中的参数是一一对应的关系。同时 from又是对应的Map中的key,to又是对应布局文件中相应组件的ID。

1、3使用SimpleCursorAdapter 构建ListView

相比SimpleAdapter,SimpleCursorAdapter 就是方便把从游标得到的数据进行列表显示,并可以把指定的列映射到对应的组件中。SimpleCursorAdapter的构造函数与SimpleAdapter的区别就是多了一个Cursor c:SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to),Cursor就是游标,如果你不清楚游标的概念,就想像成数据查询后的一个结果集。下面是一个通过SimpleCursorAdapter 使用ListView显示系统通讯录中联系人的例子。package com.liuzhichao.listview;

import android.app.Activity;

import android.database.Cursor;

import android.os.Bundle;

import android.provider.ContactsContract.Contacts;

import android.widget.ListView;

import android.widget.SimpleCursorAdapter;

public class SimpleCursorAdapterActivity extends Activity {

private ListView mListView;

@Override

protected void onCreate(Bundle savedInstanceState) {

// TODO Auto-generated method stub

super.onCreate(savedInstanceState);

mListView = new ListView(this);

Cursor cursor=this.getContentResolver().query(Contacts.CONTENT_URI, null, null, null, null);

SimpleCursorAdapter adapter=new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_2, cursor,

new String[]{Contacts.DISPLAY_NAME},

new int[]{android.R.id.text1});

mListView.setAdapter(adapter);

setContentView(mListView);

}

}

注意:在读取系统通讯录时,需要如下权限:

左图上是系统通讯录中的联系人,右图是运行的结果。

1、4使用自定义Adapter构建ListView

当我们使用系统自带的ArrayAdapter、SimpleAdapter和SimpleCursorAdapter适配器时,对于事件的响应只能局限在一个行单位。假设一行里面有一个按钮和一个图片控件,它们之间的响应操作是不一样的。若采用系统自带的适配器,就不能精确到每个控件的响应事件。这时,我们一般采取自定义适配器来实现这个比较精确地请求。我们再新建一个MyAdapterListActivity继承Activity,使用自定义适配器来实现SimpleAdapterListView中的效果,并新增一个多选框和按钮。效果如下:

MyAdapterListActivity.java:package com.liuzhichao.listview;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import android.app.Activity;

import android.app.AlertDialog;

import android.content.Context;

import android.os.Bundle;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.Button;

import android.widget.CheckBox;

import android.widget.CompoundButton;

import android.widget.ImageView;

import android.widget.ListView;

import android.widget.TextView;

public class MyAdapterListActivity extends Activity {

//分别定义通讯录中的用户名、电话、地区等信息

private String[] info_Names={"史珍香","赖月京","秦寿生","刘产","扬伟","范剑"};

private String[] info_Phones={"13844445144","13844444444","13444445144","13544445144","13644445144","13744445144"};

private String[] info_Regions={"火星","水星","木星","月球","美国","未知"};

//定义一个ArrayList数组,每一条数据对应通讯录中的一个联系人信息

private ArrayList> mInfos= new ArrayList>();

//定义一个ListView

private ListView mListView;

@Override

protected void onCreate(Bundle savedInstanceState) {

// TODO Auto-generated method stub

super.onCreate(savedInstanceState);

//new一个ListView

mListView = new ListView(this);

//添加联系人信息

for(int i=0;i

Map item = new HashMap();

item.put("img", R.drawable.contact_img);

item.put("name", info_Names[i]);

item.put("phone", info_Phones[i]);

item.put("region", info_Regions[i]);

mInfos.add(item);

}

MyAdapter adapter = new MyAdapter(this, mInfos);

mListView.setAdapter(adapter);

setContentView(mListView);

}

private class MyAdapter extends BaseAdapter {

private Context context; //运行上下文

private List> listItems; //联系人信息集合

private LayoutInflater listContainer; //视图容器

private boolean[] hasChecked; //记录联系人选中状态

public final class ListItemView{ //自定义控件集合

public ImageView img;

public TextView name;

public TextView phone;

public TextView region;

public CheckBox check;

public Button detail;

}

public MyAdapter(Context context, List> listItems) {

this.context = context;

listContainer = LayoutInflater.from(context); //创建视图容器并设置上下文

this.listItems = listItems;

hasChecked = new boolean[getCount()];

}

public int getCount() {

return listItems.size();

}

public Object getItem(int position) {

return null;

}

public long getItemId(int position) {

return 0;

}

public View getView(int position, View convertView, ViewGroup parent) {

final int selectID = position;

ListItemView listItemView = null;

if (convertView == null) {

listItemView = new ListItemView();

//获取list_item布局文件的视图

convertView = listContainer.inflate(R.layout.myinfo, null);

//获取控件对象

listItemView.img = (ImageView)convertView.findViewById(R.id.info_img);

listItemView.name = (TextView)convertView.findViewById(R.id.info_name);

listItemView.phone = (TextView)convertView.findViewById(R.id.info_phone);

listItemView.region = (TextView)convertView.findViewById(R.id.info_region);

listItemView.detail= (Button)convertView.findViewById(R.id.btn);

listItemView.check = (CheckBox)convertView.findViewById(R.id.checkBox);

//设置控件集到convertView

convertView.setTag(listItemView);

//设置联系人信息

listItemView.img.setBackgroundResource((Integer) listItems.get(

position).get("img"));

listItemView.name.setText((String) listItems.get(

position).get("name"));

listItemView.phone.setText((String) listItems.get(

position).get("phone"));

listItemView.region.setText((String) listItems.get(

position).get("region"));

//More按钮事件

listItemView.detail.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {

showDetailInfo(selectID);

}

});

// 注册多选框状态事件处理

listItemView.check

.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {

public void onCheckedChanged(CompoundButton buttonView,

boolean isChecked) {

//记录联系人选中状态

checkedChange(selectID);

}

});

}else {

listItemView = (ListItemView)convertView.getTag();

}

return convertView;

}

/**

* 记录勾选了哪个联系人

* @param checkedID 选中的联系人序号

*/

private void checkedChange(int checkedID) {

hasChecked[checkedID] = !hasChecked(checkedID);

}

/**

* 判断联系人是否选择

* @param checkedID 联系人序号

* @return 返回是否选中状态

*/

public boolean hasChecked(int checkedID) {

return hasChecked[checkedID];

}

/**

* 显示物品详情

* @param clickID

*/

private void showDetailInfo(int clickID) {

new AlertDialog.Builder(context)

.setIcon(Integer.parseInt(listItems.get(clickID).get("img").toString()))

.setTitle(listItems.get(clickID).get("name")+"详细信息")

.setMessage("电话:"+listItems.get(clickID).get("phone").toString()+" 地区:"+listItems.get(clickID).get("region").toString())

.setPositiveButton("确定", null)

.show();

}

}

}

myinfo.xml:<?xml version="1.0" encoding="utf-8"?>

android:layout_width="fill_parent"

android:layout_height="fill_parent" >

android:id="@+id/info_img"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="3dp"/>

android:id="@+id/info_name"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_toRightOf="@id/info_img"

android:layout_marginTop="5dp"/>

android:id="@+id/info_phone"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_below="@id/info_name"

android:layout_toRightOf="@id/info_img"

android:layout_alignBaseline="@id/info_img"/>

android:id="@+id/info_region"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_toRightOf="@id/info_phone"

android:layout_alignBaseline="@id/info_phone"

android:layout_marginLeft="10dip"/>

android:id="@+id/checkBox"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="5dp"

android:layout_alignBaseline="@id/info_img"

android:layout_toRightOf="@id/info_region"/>

android:id="@+id/btn"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignBaseline="@id/checkBox"

android:layout_toRightOf="@id/checkBox"

android:text="More..."

/>

2、让Activity继承ListActivity构建ListView

如果程序的窗口仅仅需要显示一个列表,则可以让Activity直接继续ListActivity来实现。ListActivity的子类无需调用setContentView()方法来显示某个界面,而是可以直接传入一个Adapter,ListActivity的子类就可以呈现出一个列表。package com.liuzhichao.listview;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.Map;

import android.app.ListActivity;

import android.os.Bundle;

import android.widget.SimpleAdapter;

public class ListActivityList extends ListActivity {

//分别定义通讯录中的用户名、电话、地区等信息

private String[] info_Names={"***","***","***","***","***","***"};

private String[] info_Phones={"13844445144","13844444444","13444445144","13544445144","13644445144","13744445144"};

private String[] info_Regions={"火星","水星","木星","月球","美国","未知地区"};

//定义一个ArrayList数组,每一条数据对应通讯录中的一个联系人信息

private ArrayList> mInfos= new ArrayList>();

@Override

protected void onCreate(Bundle savedInstanceState) {

// TODO Auto-generated method stub

super.onCreate(savedInstanceState);

//添加联系人信息

for(int i=0;i

Map item = new HashMap();

item.put("img", R.drawable.contact_img);

item.put("name", info_Names[i]);

item.put("phone", info_Phones[i]);

item.put("region", info_Regions[i]);

mInfos.add(item);

}

//定义一个SimpleAdapter

SimpleAdapter adapter = new SimpleAdapter(this, mInfos, R.layout.info,

new String[]{"img","name","phone","region"},

new int[]{R.id.info_img,R.id.info_name,R.id.info_phone,R.id.info_region});

//本例中没有声明一个ListView,但通过继承ListActivity使用setListAdapter然后传入一个适配器即可直接显示一个列表。

setListAdapter(adapter);

}

}

java list适配器_详解listview的四种适配器模式相关推荐

  1. python什么是可变参数_详解Python的三种可变参数

    可变参数 可变参数应该最简单,在C/C++和Java等语言中都有,就是用*号来表示,例如 def testArg(*arg) 你可以传入任意多个元素(包括0)到参数中,在函数内部会自动认为是一个元组或 ...

  2. python中什么是可变参数_详解Python的三种可变参数

    详解Python的三种可变参数 可变参数 可变参数应该最简单,在C/C++和Java等语言中都有,就是用*号来表示,例如 def testArg(*arg) 你可以传入任意多个元素(包括0)到参数中, ...

  3. java 引用传递_详解java的值传递、地址传递、引用传递

    详解java的值传递.地址传递.引用传递 一直来觉得对值传递和地址传递了解的很清楚,刚才在开源中国上看到一篇帖子介绍了java中的值传递和地址传递,看完后感受颇深.下边总结下以便更容易理解. 按照以前 ...

  4. java内部格式_详解java内部类的访问格式和规则

    详解java内部类的访问格式和规则 1.内部类的定义 定义一个类来描述事物,但是这个事物其中可能还有事物,这时候在类中再定义类来描述. 2.内部类访问规则 ①内部类可以直接访问外部类中的成员,包括私有 ...

  5. java comparator相等_详解Java中Comparable和Comparator接口的区别

    详解Java中Comparable和Comparator接口的区别 发布于 2020-7-20| 复制链接 摘记: 详解Java中Comparable和Comparator接口的区别本文要来详细分析一 ...

  6. python java混合编程_详解java调用python的几种用法(看这篇就够了)

    java调用python的几种用法如下: 在java类中直接执行python语句 在java类中直接调用本地python脚本 使用Runtime.getRuntime()执行python脚本文件(推荐 ...

  7. Java implement意思_详解JAVA中implement和extends的区别

    详解JAVA中implement和extends的区别 发布于 2020-4-14| 复制链接 摘记: 详解JAVA中implement和extends的区别extends是继承父类,只要那个类不是声 ...

  8. java sleep唤醒_详解Java中的线程让步yield()与线程休眠sleep()方法

    Java中的线程让步会让线程让出优先级,而休眠则会让线程进入阻塞状态等待被唤醒,这里我们对比线程等待的wait()方法,来详解Java中的线程让步yield()与线程休眠sleep()方法 线程让步: ...

  9. idea看java版本设置_详解IntelliJ IDEA 中如何配置多个jdk版本即(1.7和1.8两个jdk都可用)...

    详解IntelliJ IDEA 中如何配置多个jdk版本即(1.7和1.8两个jdk都可用) 有时候需要看Java源码,但是 Java 1.7 和 Java 1.8的差别的关系,有时候你想查看不同jd ...

最新文章

  1. 乐视电视明明可以降低配置,为什么偏偏要涨价?
  2. Spring boot 启动后执行特定的操作
  3. 6-3 两个有序链表序列的合并
  4. 更新node最新版本方法和 npm install -g n 运行错误
  5. Windows终止进程
  6. 8.霍夫变换:线条——介绍、参数模型、直线拟合_1
  7. python爬虫大作业爬多少数据_爬虫大作业
  8. Django 阅读笔记 - Cache
  9. OpenSSH概念和基本用法——SSH 客户端
  10. 读取npy格式的文件
  11. Linux bridge hairpin mode
  12. 秉持技术普惠的华为,致力于无处不在的联接
  13. CNN之绘画风格迁移-附源码地址
  14. JavaScript判断浏览器内核
  15. 【网络通信三】研华网关Modbus服务设置
  16. 京东内网遭开源的“顶级”SpringCloud实战手册,GitHub列为首推
  17. slurm学习笔记(一)
  18. veritas msi_使用适用于AIX 5.3和6.1的Veritas Volume Manager(VxVM)V5管理逻辑卷
  19. 半导体器件物理【19】PN结 —— 制造方法、空间电荷区、PN结平衡态
  20. Reactor编程之旅

热门文章

  1. boost::stl_interfaces模块实现最小的随机访问迭代器的测试程序
  2. BOOST使用 proto 转换进行任意类型操作的简单示例
  3. boost::pfr::tuple_element_t相关的测试程序
  4. boost::hana::div用法的测试程序
  5. boost::geometry:::detail::overlay::get_clusters用法的测试程序
  6. 基于Boost::beast模块的协程WebSocket 服务器
  7. VTK:可视化之StreamLines
  8. VTK:Utilities之UnknownLengthArray
  9. VTK:相互作用之PickableOff
  10. VTK:图片之ImageRange3D