ListView
来源:互联网 发布:mac os 病毒查杀 编辑:程序博客网 时间:2024/06/06 04:52
Android中ListView这个组件比较常用,但对初学者来说,又比较难掌握,在此分享一下我的使用经验。
ListView是以列表的形式展示数据,这里面有三个要素:数据、视图、适配器。
常用的适配器有三种:ArrayAdapter, SimpleAdapter, SimpleCursorAdapter。 【这种方法仅仅适用于每一个item形式都相同的情况】
其中SimpleAdapter扩展性最好,几乎能实现所有展示需求的列表,我在实际开发中用的全是这个,这里也只介绍这个。
假设要实现如下效果的列表视图:
下面一步步来实现。
首先设计视图,主要设计ListView里面item的显示效果,在layout中创建item.xml文件,如下:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent" android:layout_height="75dp"
- android:paddingLeft="10dp" android:paddingRight="10dp">
- <ImageView
- android:id="@+id/img"
- android:layout_height="fill_parent"
- android:layout_width="60dp"
- android:layout_alignParentLeft="true" />
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_height="fill_parent"
- android:layout_width="fill_parent" android:layout_toRightOf="@id/img"
- android:paddingLeft="8dp">
- <TextView
- android:id="@+id/title1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="#cbcaca"
- android:textSize="20dp" />
- <TextView
- android:id="@+id/title2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="#cbcaca"
- android:textSize="14dp" />
- <TextView
- android:id="@+id/time"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="#cbcaca"
- android:textSize="12dp" />
- </LinearLayout>
- <CheckBox
- android:id="@+id/checked"
- android:layout_height="fill_parent"
- android:layout_width="wrap_content"
- android:layout_alignParentRight="true"
- android:checked="false"
- android:focusable="false" />
- </RelativeLayout>
此xml文件定义列表中每个项目的布局,如果想要不同的布局,修改此文件的布局即可。
这个文件中给每个需要在程序中动态赋值的地方都取了id,看到后面的代码时,注意对应关系。
然后是适配器和数据,这两个联系比较紧密,就放一起了。
先上代码:
- //获取ListView对象
- ListView mListView = (ListView) findViewById(R.id.listview);
- //下面是数据映射关系,mFrom和mTo按顺序一一对应
- String[] mFrom = new String[] {"img", "title1", "title2", "time"};
- int[] mTo = new int[] {R.id.img, R.id.title1, R.id.title2, R.id.time};
- //获取数据,这里随便加了10条数据,实际开发中可能需要从数据库或网络读取
- List<Map<String, Object>> mList = new ArrayList<Map<String, Object>>();
- Map<String,Object> mMap = null;
- for (int i = 0; i < 10; i++) {
- mMap = new HashMap<String,Object>();
- mMap.put("img", R.drawable.icon);
- mMap.put("title1", "标题");
- mMap.put("title2", "副标题");
- mMap.put("time", "2011-08-15 09:00");
- mList.add(mMap);
- }
- //创建适配器
- SimpleAdapter mAdapter = new SimpleAdapter(this, mList, R.layout.item, mFrom, mTo);
- mListView.setAdapter(mAdapter);
这里要注意对应关系,Layout中的id,程序中对它的引用,Map中的数据。
到这里已经实现了上面那张图的效果。但是程序需要一些交互操作,比如单击某一项,长按某一项,怎么办?
看下面:
添加点击事件:
- mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- @SuppressWarnings("unchecked")
- // 获取被点击的item所对应的数据
- HashMap<String,Object> map = (HashMap<String, Object>) parent.getItemAtPosition(position);
- //下面是你的其他事务逻辑
- }
- });
这里可以通过position获取被点击的item所对应的Map数据,拿到这个数据了,还怕有什么功能实现不了吗?
举个最常见的例子,数据是从数据库里取的,每条数据有唯一的id,点了某一项之后,需要得到这个id进行数据操作,怎么办?很简单,在准备数据的时候,往Map中多添加一条数据,map.put("id",id),在上面的事件处理中,可以通过(Long) map.get("id")来获取id(此处假设id是long类型),取到id之后就可以进行数据库操作了。放心,添加的额外数据不会影响View的显示,因为有对应关系在。
长按事件和这个类似,无非是注册OnItemLongClickListener事件,在此就不列代码了。
还有最后一个问题,界面中每个item后面显示了一个单选框,明显是为批处理留的,该如何实现呢?
仔细想一下,会发现难点在于单选框状态的记录及获取。下面是我的方法:
在定义SimpleAdapter对象的时候,重写它的getView方法。如下:
- mAdapter = new SimpleAdapter(this, pictureList, R.layout.picturelist, mFrom, mTo) {
- @Override
- public View getView(final int position, View convertView, ViewGroup parent) {
- View view = super.getView(position, convertView, parent);
- @SuppressWarnings("unchecked")
- final HashMap<String,Object> map=(HashMap<String, Object>)this.getItem(position);
- //获取相应View中的Checkbox对象
- CheckBox checkBox = (CheckBox)view.findViewById(R.id.checked);
- checkBox.setChecked((Boolean) map.get("checked"));
- //添加单击事件,在map中记录状态
- checkBox.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- map.put("checked", ((CheckBox)view).isChecked());
- }
- });
- return view;
- }
- };
在其他地方获取状态并处理:
- //获取列表中的项目总数
- int count = pictureListView.getCount();
- Map<String, Object> map = null;
- boolean isChecked;
- long id;
- for (int i = 0; i < count; i++) {
- map = (Map<String, Object>) pictureListView.getItemAtPosition(i);
- isChecked = (Boolean) map.get("isChecked");
- if (isChecked) {
- id = (Long) map.get("id");
- //被选中的逻辑
- } else {
- id = (Long) map.get("id");
- //未被选中的逻辑
- }
- }
- //如果操作过程中对列表内容进行了添加或删除,需要调用下面这个方法来更新视图
- mAdapter.notifyDataSetChanged();
还有一点忘了写了,demo中的图片是drawable里面的图片,如果map中只有图片的地址,如何把它转成drawable对象显示出来呢?我在这里也研究了好久,map中放入drawable对象传过去好像没用,不会显示,怎么办?好在前面有重写SimpleAdapter的getView方法。map中把图片地址放进去,在getView方法里面,把此地址转成drawable对象,然后设置给ImageView,大功告成!代码如下:
- mAdapter = new SimpleAdapter(this, pictureList, R.layout.picturelist, mFrom, mTo) {
- @Override
- public View getView(final int position, View convertView, ViewGroup parent) {
- View view = super.getView(position, convertView, parent);
- @SuppressWarnings("unchecked")
- final HashMap<String,Object> map=(HashMap<String,Object>)this.getItem(position);
- ImageView imageView = (ImageView)view.findViewById(R.id.img);
- FileInputStream fin;
- try {
- if(map.get("img") == null){
- throw new IOException();
- }
- fin = getApplicationContext().openFileInput((String) map.get("img"));
- imageView.setImageDrawable(Drawable.createFromStream(fin, "src"));
- fin.close();
- } catch (FileNotFoundException e) {
- imageView.setImageResource(R.drawable.default);
- } catch (IOException e) {
- imageView.setImageResource(R.drawable.default);
- }
- return view;
- }
- };
好了,就到这里了。
AdapterView的使用:【在ListView中看到的AdapterView】
继承关系:
View<-ViewGroup<-AdapterView<-ListView,GridView,Spinner,Gallery
功能:
一个Adapter对象作为一个AdapterView和View底层数据之间的桥,提供对data Items的存取,同时负责针对每个Data如何渲染到对应的View中。
1、数据库Cursor: SimpleCursorAdapter
结构:
SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to)
功能:
将游标Cursor中的一行转换为容器控件的子容器。
2、String[]: ArrayAdapter
将字符串数组中的数据转换为容器控件的子容器。
3、List: SimpleAdapter
结构:
SimpleAdapter (Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
参数:
context:关联SimpleAdapter运行着的视图的上下文,一般而言也就是Activity。
data:一个Map的列表。在列表中的每个条目对应列表中的一行,应该包含所有在from中指定的条目。
resource :一个定义列表项目的视图布局的资源唯一标识。布局文件将至少应包含哪些在to中定义了的名称。
from:一个将被添加到Map上关联每一个项目的列名称的列表
to:应该在参数from显示列的视图。这些应该全是TextView。在列表中最初的N视图是从参数from中最初的N列获取的值。
使用AdapterView来绑定数据
AdapterView是一个ViewGroup子类, 它的子View是有一个Adapter决定的, 而该Adapter绑定某种类型的数据. AdapterView在你希望显示储存的数据(相对于资源字符串或者图片)时比较有用.
Gallery, ListView, 和 Spinner是AdapterView子类的例子, 你可以使用它们绑定特定类型的数据并按照一定方式来显示它们.
AdapterView对象有两个主要任务:
Filling the Layout with Data 为布局填充数据
将数据插入布局一般是通过将AdapterView类绑定到一个Adapter完成的. Adapter从一个外部资源获取数据(可能是代码直接提供,也可能是从设备上的一个数据库查到的数据组成的一个列表).
下列代码做了两件事情:
// Get a Spinner and bind it to an ArrayAdapter that
// references a String array.
Spinner s1 = (Spinner) findViewById(R.id.spinner1);
ArrayAdapter adapter = ArrayAdapter.createFromResource(
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s1.setAdapter(adapter);
// Load a Spinner and bind it to a data query.
private static String[] PROJECTION = new String[] {People._ID, People.NAME};
Spinner s2 = (Spinner) findViewById(R.id.spinner2);
Cursor cur = managedQuery(People.CONTENT_URI, PROJECTION, null, null);
SimpleCursorAdapter adapter2 = new SimpleCursorAdapter(this,
adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s2.setAdapter(adapter2);
注意必须People._ID 列必须和CursorAdapter 一起使用, 否则你会得到异常.
如果在你的应用程序生命周期中, 你改变了你的Adapter管理的数据, 你应该调用notifyDataSetChanged(). 这将使附加的View刷新.
Handling User Selections 处理用户选择
使用AdapterView.OnItemClickListener来获取用户的选择.
// Create a message handling object as an anonymous class.
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
};
// Now hook into our object and set its onItemClickListener member
// to our class handler object.
mHistoryView = (ListView)findViewById(R.id.history);
mHistoryView.setOnItemClickListener(mMessageClickedHandler)
- listview
- listview
- listview
- ListView
- ListView
- listview
- listview
- listView
- ListView
- ListView
- ListView
- listview
- LIstView
- ListView
- listview
- ListView
- ListView
- ListView
- 暂别CSDN一段时间
- Linux命令 - sed 简明教程
- 《Thinking In Algorithm》01.Array与ArrayList的区别(java)
- mean shift tracking
- dialog
- ListView
- 移植uCOS-II到Cortex-M3平台 (补遗)
- 关于安全漏洞的一个网站?
- Java 中的单例模式,看完这一篇就够了
- Android ListView item 选中高亮显示之高效实现方式
- 彩色字ClipText
- oracle 闪回功能详解
- RHEL CentOS 安装 EPEL RPMForge扩展软件源
- java实现Hbase中的查询(一)Filter方式