首页 > 代码库 > android ListView与Adapter详解
android ListView与Adapter详解
ListView可以说是android开发中非常非常常用的一个控件,今天整理了一下,ListView相关的东西,记录于此。(很奇怪,总感觉只有自己总结写过的东西才是属于自己的,看别人看多了,却总是心中不慎踏实)
ListView在使用中有两个作用:
一是将数据绑定到ListView的item;而是ListView的item对用户点击时间作出响应,常用的有onClickListener与onLongClickListener,当然当你需要计算用户点击的具体位置再做出响应时,可以先实现onTouchListener接口,具体可参见我之前的一篇博客!
链接
ListView的创建一般需要三个组成部分,1.为ListView中的每个item定义对应的View;2.为该View填入数据,可以是图片或这数据等;3.为ListView绑定Adapter(适配器)。ListView作为一个典型的adapterView,必须由adapter作为桥梁将要显示的数据和ListView连结起来.(至于Adapter绑定数据的内部实现已经由framework封装好了,你所需要的就是去调用它。虽然这样很不爽,但是在你对framework做不了太大改动的时候,就先这样用着吧,毕竟省心省力)
接下来说一下,常用的Adapter以及它们各自的适用场景,了解这些才能真正做到物尽其用,而非醒悟后大叹:”杀鸡焉用牛刀”。
1.ArrayAdapter
常用来绑定一个数组或者List,支持泛型ArrayAdapter<T>。可用于先是一行简单的文本信息。
2.SimpleAdapter
可以显示比较复杂的列表,属于中自由度的Adapter。包括每行显示图片、文字等,但不能对列表进行后期加工(在java代码中加工),也是只是单纯的负责显示(当然可以设计复杂点的布局来显示复杂列表),例如,每行显示不同背景等。。但是你要是想在item的view中添加按钮并响应用户操作的话,SimpleAdapter就不能满足要求了,因为当用户点击到item商德button时点击事件会被item本身的onClickListener所拦截。此时你就需要继承BaseAdapter来实现自己的Adapter了。
3.SimpleCursorAdapter
该Adapter常用来绑定游标查询得到的数据。例如查询联系人数据库等。
4.BaseAdapter
可以实现复杂的列表布局,由于BaseAdapter是一个抽象类,使用该类需要自己写一个适配器继承该类,正是由于继承了该类,需要我们重写一些方法,让我们可以在代码里控制列表的样式,更加灵活。
常用的Adapter的用法以及各自的使用场景就这些,so,是不是觉得很简单啊。接下来我们一一讲解一下。
一.ArrayAdapter
效果图
public ArrayAdapter (Context context, int resource, T[] objects)
上面是ArrayAdapter的构造器,我们使用时
new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,muList)
想必很清楚了吧,我们使用ArrayAdapter需要传入三个参数:
1.当前上下文;
2.为ListView的item绑定的XML布局文件,上面是android自带的,你完全可以自己定义;
3.数据源,可以使数组或者List集合;
java 代码如下:
package com.example.ListViewDemo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.*;
import com.example.IntentTest.R;
import java.util.ArrayList;
import java.util.List;
/**
* @author canglangwenyue
* 最简单的listview adapter适用于在listview中显示一组String或者一个list的内容
*/
public class MyActivity extends Activity {
/**
* Called when the activity is first created.
*/
ListView listView;
private List<String> muList = new ArrayList<String>();
private String[] intentDataString = {"ArrayAdapter","SimpleAdapter","BaseAdapter","SimpleCursorAdapter"};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
for (int i=0;i<intentDataString.length;i++) {
muList.add(intentDataString[i]);
}
listView = (ListView) findViewById(R.id.my_listView);
/*
android.R.layout.simple_list_item_multiple_choice
android.R.layout.simple_list_item_checked
许设置listView.lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
*/
listView.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,muList));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
/*Toast当前选中的listView_item的内容*/
mySwitcher(muList.get(position).toString());
}
});
}
private void mySwitcher(String type) {
if (type=="SimpleAdapter") {
startActivity(new Intent(MyActivity.this, simpleAdapter.class));
}else if (type=="ArrayAdapter") {
Toast.makeText(MyActivity.this,"我一直在这里为你守候",Toast.LENGTH_LONG).show();
}
else if (type=="SimpleCursorAdapter") {
startActivity(new Intent(MyActivity.this, simpleCursorAdapter.class));
} else if (type=="BaseAdapter") {
startActivity(new Intent(MyActivity.this, baseAdapter.class));
}
}
}
二.SimpleAdapter
效果图
SimpleAdapter相对于ArrayAdapter的适用范围就大了很多。
public SimpleAdapter(Context context, List<? extends Map<String, ?>> data,
int resource, String[] from, int[] to) {
mData = http://www.mamicode.com/data;"keyword" style="">from
;
mTo = to;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
上面是SimpleAdapter的构造器,我们使用时
new SimpleAdapter(this, getData(), R.layout.simpleadapteritem, new String[]
{"img", "title", "info"}, new int[]{R.id.imageView, R.id.textView,
R.id.textView2});
我们在此处传入了五个参数:
1.当前上下文;
2.绑定的HashMap数据;
3.ListView的item的XML布局文件;
4.后两个参数的作用是将List<Map<String, Object>>中的数据源的键对应到定义布局的View;
java 代码如下:
package com.example.ListViewDemo;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import com.example.IntentTest.R;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by canglangwenyue on 12/3/14.
*/
public class simpleAdapter extends Activity {
private ListView simpleListView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simpleadapter);
simpleListView = (ListView) findViewById(R.id.simplelistView);
SimpleAdapter simpleAdapter = new SimpleAdapter(this, getData(), R.layout.simpleadapteritem, new String[]{"img", "title", "info"}, new int[]{R.id.imageView, R.id.textView, R.id.textView2});
simpleListView.setAdapter(simpleAdapter);
}
private List<Map<String, Object>> getData() {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map = new HashMap<String, Object>();
map.put("img", R.drawable.ic_launcher);
map.put("title", "德玛西亚");
map.put("info", "德玛西亚万岁");
list.add(map);
map = new HashMap<String, Object>();
map.put("img", R.drawable.ic_launcher);
map.put("title", "卡牌大师");
map.put("info", "没有一场公平的比赛,也不要去玩一场公平的比赛");
list.add(map);
map = new HashMap<String, Object>();
map.put("img", R.drawable.ic_launcher);
map.put("title", "炮手");
map.put("info", "好想射点什么");
list.add(map);
map = new HashMap<String, Object>();
map.put("img", R.drawable.ic_launcher);
map.put("title", "炼金");
map.put("info", "摇还是不摇这是一个问题··");
list.add(map);
map = new HashMap<String, Object>();
map.put("img", R.drawable.ic_launcher);
map.put("title", "死歌");
map.put("info", "Their pain,is my……pleasure!");
list.add(map);
map = new HashMap<String, Object>();
map.put("img", R.drawable.ic_launcher);
map.put("title", "寡妇");
map.put("info", "黑夜就是我的面纱··");
list.add(map);
return list;
}
}
使用simpleAdapter的数据一般都是用HashMap构成的列表,列表的每一节对应ListView的每一个item。通过
SimpleAdapter的构造函数,将HashMap的每个键的数据映射到布局文件中对应控件上。这个布局文件一般根据
自己的需要来自己定义。梳理一下使用SimpleAdapter的步骤。
(1)根据需要定义ListView每行所实现的布局。
(2)定义一个HashMap构成的列表,将数据以键值对的方式存放在里面。
(3)构造SimpleAdapter对象。
(4)将LsitView绑定到SimpleAdapter上。
三.SimpleCursorAdapter
效果图
@Deprecated
public SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c);
mTo = to;
mOriginalFrom = from;
findColumns(c, from);
}
上面是SimpleCursorAdapter的构造函数,我们使用时
new SimpleCursorAdapter(this, R.layout.simplecursoradapteritem, cursor,
new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME},
new int[]{R.id.people_name});
我们在此处传入了五个参数,这里参数的作用和SimpleAdapter里面类似,只是操作对象不一样:
1.上下文;
2.item的布局文件;
3.Cursor的引用;
4.将Cursor查询到的相应的值绑定到item布局中对应的View;
java 代码如下:
package com.example.ListViewDemo;
import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import com.example.IntentTest.R;
/**
* Created by canglangwenyue on 12/3/14.
*/
public class simpleCursorAdapter extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simplecursoradapter);
Cursor cursor=getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,null,null,null,null);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.simplecursoradapteritem, cursor,
new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME},
new int[]{R.id.people_name});
ListView listView = (ListView) findViewById(R.id.simplecusorlistView);
listView.setAdapter(adapter);
}
}
四.BaseAdapter
效果图
BaseAdapter的用法可以参见我文章开始给的那个链接那篇文章已经讲得很详细了,大家可以参考一下。BaseAdapter为我们提供了很大的灵活性,当然代价就是我们需要自己来完成更多的工作。原因已经陈述过了。
这里只给出这个例子中的java 代码:
package com.example.ListViewDemo;
import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.view.ViewGroup;
import android.widget.*;
import com.example.IntentTest.R;
import java.util.ArrayList;
import java.util.List;
/**
* Created by canglangwenyue on 12/3/14.
*/
public class baseAdapter extends Activity {
private ListView personListView;
private List<Person> personList;
private PersonAdapter personAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.baseadapter);
personList = new ArrayList<Person>();
personListView = (ListView) findViewById(R.id.baseadapterlistView);
personList = initContacts();
personAdapter = new PersonAdapter();
personListView.setAdapter(personAdapter);
}
private List<Person> initContacts() {
Cursor cursor = getContentResolver().query(Phone.CONTENT_URI,charChangeutil.PHONES_PROJECTION,null,null,null);
personAdapter = new PersonAdapter();
Person person = null;
for (cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()){
person = new Person();
person.setName(cursor.getString(0));
person.setPhoneNumber(cursor.getString(1));
personList.add(person);
}
cursor.close();
return personList;
}
class ViewHolder {
private TextView personIcon;
private TextView personName;
public ViewHolder(View view) {
personIcon = (TextView) view.findViewById(R.id.personNameTextView);
personName = (TextView) view.findViewById(R.id.personNumberTextView);
view.setTag(this);
}
}
class PersonAdapter extends BaseAdapter {
@Override
public int getCount() {
return personList.size();
}
@Override
public Object getItem(int position) {
return personList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView==null) {
convertView = View.inflate(getApplicationContext(),R.layout.baseadapteritem,null);
new ViewHolder(convertView);
}
ViewHolder holder = (ViewHolder) convertView.getTag();
Person person = personList.get(position);
holder.personIcon.setText(person.getName());
holder.personName.setText(person.getPhoneNumber());
Button button = (Button) convertView.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(baseAdapter.this,"Don‘t touch me!",Toast.LENGTH_LONG).show();
}
});
return convertView;
}
}
}
关于ListView与Adapter的介绍大概就这些了。最后简单看一下ListView的优化相关:
代码中getView()方法不容易理解。其实完全可以不用所谓的convertView和ViewHolder,直接导入布局并且设置控件显示的内容就可以了。但是这意味着有多少行数据就需要绘制多少行ListView,这显然是不可取的。这里采用了一种优化的方法。
最后,附上demo点此下载
android ListView与Adapter详解