ListView是Android中最为常用的列表类型控件,ListView中的选择项目中样式很多有的是纯文字的、有的还可以带有图片。它的继承关系如下:
java.lang.Object
↳ android.view.View
↳ android.view.ViewGroup
↳ android.widget.AdapterView<T extends android.widget.Adapter>
↳ android.widget.AbsListView
↳ android.widget.ListView
android.widget.ListView继承了android.view.ViewGroup。
首先看一个纯文本的ListView例子,案例运行后会出现一个城市列表如图6-8所示,选择某个城市,弹出一个Toast,关于Toast的概念和使用会在下一节中介绍。
图6-8 ListView
程序代码请参考代码清单6-4:
【代码清单6-4】 chapter6_3/src/com/work/ListView_1_Activity.java
public class ListView_1_Activity extends Activity {
private ListView listview;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview_activity);
listview = (ListView)findViewById(R.id.ListView01);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, mStrings);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, int pos,
long id) {
Toast.makeText(ListView_1_Activity.this, mStrings[pos],
Toast.LENGTH_SHORT).show();
}
});
}
private String[] mStrings = {
"北京市", "天津市", "上海", "重庆", "乌鲁木齐", …};
}
对 于ArrayAdapter应该已经很熟悉了,其中的android.R.layout.simple_list_item_1是使用系统的布局样式。 Android系统本身提供了很多的这样的布局文件,但是有的适合于ListView控件,有的适合于Spinner控件,有的适合于它的列表控件,这是 使用时需要注意的。
在这种方式下,需要在布局文件listview_activity.xml中添加ListView控件:
<ListView android: };
…
}
自定义的Adapter是EfficientAdapter,EfficientAdapter的相关代码请参考代码清单6-7:
【代码清单6-7】 chapter6_3/src/com/work/ListViewIcon_3.java
private static class EfficientAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private Bitmap mIcon0;
private Bitmap mIcon1;
… …
public EfficientAdapter(Context context) {
mInflater = LayoutInflater.from(context);
mIcon0 = BitmapFactory.decodeResource(context.getResources(), R.drawable.noicon);
mIcon1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.beijing);
… …
}
public int getCount() {
return DATA.length;
}
public Object getItem(int position) {
return DATA[position];
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.main, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.textview);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(DATA[position]);
switch(position)
{
case 0:
holder.icon.setImageBitmap(mIcon1);
break;
case 1:
holder.icon.setImageBitmap(mIcon2);
break;
…
default:
holder.icon.setImageBitmap(mIcon0);
break;
}
return convertView;
}
static class ViewHolder {
TextView text;
ImageView icon;
}
}
编写自定义Adapter可以继承BaseAdapter类,如果是数据库使用可以继承CursorAdapter。在本例中继承了BaseAdapter类,BaseAdapter是一个抽象类,必须在它的子类中实现下面的方法:
• int getCount() 返回总数据源中总的记录数;
• Object getItem(int position) 根据选择的项目的位置,获得选择的数据源中某个项目的数据;
• long getItemId(int position) 根据选择的项目的位置;
• View getView(int position, View convertView, ViewGroup parent) 获得要展示的项目View对象。
这 里最为麻烦的方法就是getView(),getView()方法是ListView的每个列表项目绘制在屏幕上时被调用。该方法其中的一个参数是 convertView,在ListView第一次显示列表项目的时候,convertView是null值。当向上滑动屏幕时候,屏幕上面的列表项目退 出屏幕,屏幕下面原来不可见的列表项目会进入屏幕,这个时候的convertView不是null值,下面代码的处理对于提供ListView控件提高性 能是至关重要的。
if (convertView == null) {
convertView = mInflater.inflate(R.layout.main, null);
holder = new ViewHolder();
holder.text = (TextView) convertView
.findViewById(R.id.textview);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
只 有在convertView为null时才去实例化控件,创建convertView对象、holder对象,其中convertView对象是通过 mInflater.inflate(R.layout.main, null)方法,从一个main.xml布局文件中加载并创建的。
而在convertView非null的时候不会实例化控件,否则每次都要实例化控件,当列表项目很多时,用户反复滑动屏幕会有“卡”的感觉,不再流畅了。
ViewHolder 类是将每一个项目中的控件封装起来的类,可以在convertView 为null时候创建ViewHolder类的实例holder,然后通过convertView.setTag(holder);把它放到 convertView中,而在convertView非null时候,再通过convertView.getTag()过的一个ViewHolder类 的实例,这样在翻屏的时候就不会反复创建ViewHolder实例对象了,就本例而言只是创建了9个ViewHolder实例。
出自《Android开发案例驱动教程》第六章