这一篇整理一些ListView的基本知识。
PartA翻译自API Guide:
(A)API Guide
当layout内容是动态的或者不是预先决定好的,可以使用AdapterView的子类动态完成layout的填充。
AdapterView的子类使用Adapter来bind data到它的layout里面。Adapter的角色是数据源和AdapterView layout的中间人——Adapter从数组、数据库等处取出数据然后把每个条目转换成可以加进AdapterView layout的一个view。
你可以通过给Adapter建立AdapterView的形式来填充ListView、GridView等AdatperView。这个操作会把外部数据建立成一个view,每一个view代表一个数据条目。
Android提供很多Adapter的子类来给AdapterView获取数据、建立view。两种最常见的adapter是:
当你的数据源是array(数组)的时候使用这个adapter。默认地,ArrayAdapter通过对每个list item调用toString()并且把内容放进TextView中来为每个array item建立一个view。
例如,当你有一个字符串数组想要展示在ListView里面,用构造函数来初始化一个新的ArrayAdapter并且为每个string和string array指定一个latyout。
ArrayAdapter
android.R.layout.simple_list_item_1, myStringArray);
构造函数的参数是:
然后只要在你的ListView中调用setAdapter():
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
为了自定义每个item的外观,你可以为你的数组对象复写(override)的toString()方法。或者建立一个不是TextView的view比如ImageView,继承ArrayAdapter类并且复写getView()来反悔你想为每个item准备的view类型。
当你的数据来自Cursor的时候使用这个adapter。使用SimpleCursorAdapter,你必须为Cursor中的每一行指定一个layout。例如,如果你想建立一个包含了人名和电话号码的表,你可以使用一个返回Cursor的查询(query),Corsor中一行对应一个人,列则对应人名和电话号码。然后你建立一个字符串数组来指定Cursor中的哪些列你想要放置到result的layout里面,建立一个integer数组来指定列应该被放置到的对应的view:
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};
int[] toViews = {R.id.display_name, R.id.phone_number};
When you instantiate the [SimpleCursorAdapter](https://developer.android.com/reference/android/widget/SimpleCursorAdapter.html)
, pass the layout to use for each result, the [Cursor](https://developer.android.com/reference/android/database/Cursor.html)
containing the results, and these two arrays:
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
ListView listView = getListView();
listView.setAdapter(adapter);
The [SimpleCursorAdapter](https://developer.android.com/reference/android/widget/SimpleCursorAdapter.html)
then creates a view for each row in the [Cursor](https://developer.android.com/reference/android/database/Cursor.html)
using the provided layout by inserting each fromColumns
item into the corresponding toViews
view.
.
If, during the course of your application's life, you change the underlying data that is read by your adapter, you should call [notifyDataSetChanged()](https://developer.android.com/reference/android/widget/ArrayAdapter.html#notifyDataSetChanged())
. This will notify the attached view that the data has been changed and it should refresh itself.
你可以通过实现AdapterView.OnItemClickListener接口来处理点击AdapterView中每个条目的点击事件。比如:
// Create a message handling object as an anonymous class. private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { // Do something in response to the click } }; listView.setOnItemClickListener(mMessageClickedHandler);
(B)eoe
1)ArrayAdapter
listview在findViewById获取布局之后,可以用setAdapter()方法添加元素,它的参数是ListAdapter,子类有很多,比如ArrayAdapter
*三种Adapter的数据源不同
1. String[]: ArrayAdapter
2. List
ArrayAdapter
adapter = new ArrayAdapter
array.add("Hello");//取决于前面的泛型
array.add("there");
然后介绍了自定义一个类作为泛型里的类型,ListCellData,里面有get set方法,然后在adapter里像下面这样初始化:
adapter.add(new ListCellData("小明","男","17"));
之后发现返回的是乱码,说是因为这里返回的是函数的toString()方法的返回值(构造函数没有返回值,但是每个类的父类Object有一个toString()方法可以重写)。
于是:
@override
public String toString(){
return this.getUserName(); //
}
然后介绍了lv.setOnItemClickListener(this)绑定监听器的方法。之前为什么要定义ListCellAdapter?这里体现出来:
可以返回自定义的类型,然后去get类中的变量。这样的话比如一条答案,可以把他们所有的属性封装成一个数据类型,list.add的时候add要显示的内容。
这里的position似乎很智能,似乎之前的add是一个队列,跟这里position顺序都是一一对应的。
2)用BaseAdapter自定义复杂列表
初始化一个BaseAdapter对象,它复写了getView(), getItemID(), getItem(), getCount()。
getView()只要在需要呈现列表项的时候都会被执行。
在getView()里需要创建一个视图来返回。这里返回一个textview。
getView()什么时候执行?如果在getView()里println,会发现每当显示新的item的时候,getView就会执行一次,创建一个textView。当有几百个list item的时候,这样很耗内存。
所以,要用getView的第二个参数,convertView。
convertView的意思是,当listview里的item滑出屏幕之后,view就会变成一个convertView。所以可以在convertView不为空的时候(有view滑出屏幕了),不创建新的view,而是先用convertView(这样是不是实现了只需要创建屏幕上显示的那么多个view就行了呢)。下图中注意new TextView中传的参数就是所在的类的名字。
图:convertView的示例
下面,实现一个能够呈现出图片的列表。于是新建一个customer_list_cell.xml列表项。里面有ImageView、TextView等等需要自己布局。
然后,数据要建立一个独立的类。一般要有set get方法。用构造函数给这个类里的变量传值。
接下来要实现getView()。同样重用convertView。给内部的子对象重新赋值,否则会发现后面的item跟以前会重复。
然后是在自定义的LL里面findViewById,从以前创建的LL内部查找。这一点要好好体会一下。
好了,功能完成了,但是真实开发过程不建议用BaseAdapter的匿名内部类实现。要把类之间的耦合度降低,以便写大工程。
创建一个类继承自BaseAdapter。
传Context进来。
接下来介绍了ListActivity。如果为ListActivity创建一个布局xml文件,那么这个布局文件内部必须有一个listview并且它的ID必须指定为:android:id="@android:id/list"。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章