Listview控件不像其他安卓控件那种直接拖拽到界面上就能用,而是采用类似J2EE中的MVC模型的方式使用,需要通过适配器将某种样式的数据或控件添加到其上而使用.
MVC模型实现原理是 数据模型M(Model) 存放数据,利用控制器C (Controller)将数据显示在视图V (View)上。
利用BaseAdapter实现一个ListView的步骤一般如下:
1 首先准备好需要显示在LiseView中的数据 ——List
2 然后编写2 个XML 文件 第一个文件是ListView控件所在的布局文件 第二个文件是ListVIew中每一个item的布局文件
3 创建一个继承自BaseAdapter的类
4 为ListView绑定适配器 setAdapter(继承BaseAdapter 类的实例)
5 用传统方式来覆写适配器的getView函数和getCount 函数(从参数convertView里映射布局文件,find各个控件填充数据)
6 加入ViewHolder类(定义n个控件的声明)用convertView.setTag(viewHolder)在View和Object之间关联,此目的是节省find多次的时间。
步骤一 List的使用
数据源可以有多种形式,比如是一个数组,或者是一个list 其作用是使lisview中每一行显示出数据源的每一个元素的值。
比如ListView中每一个item只有一个控件 TextView 则list可以定义成一个字符串数组,或者一个ArrayList
。
如果ListView中每一个item有很多个控件,则可以把多个控件的值类型定义成一个类如Item类 格式如下
public class Item{
String name;
String text;
int number;
int imageId;
//省略setter和getter方法
}
则此时List定义成List 并且初始化为
List<Item> listItems = new ArrayList<>();
并赋予值如下
for(int i = 0 ; i < 10 ; i ++){
Item item = new Item();
item.setName("sqf");
item.setText("Hello World");
item.setNumber(i);
item.setImageId( R.drawable.ic_launcher);
listItems.add(item);
}
或者将多个控件的值的类型包装成Map ,改成如下格式:
List<Map<String , Object>> listItems = new ArrayList<Map<String , Object>>();
Map<String, Object> map;
for(int i=0;i<10;i++)
{
map = new HashMap<String, Object>();
map.put("imageId", R.drawable.ic_launcher);
map.put("text", "hello World");
map.put("name" , "sqf");
map.put("number", i);
listItems.add(map);
}
此时list已经构建完毕,已经得到了需要加入ListView中的值了。
步骤二 编写需要ListView布局文件以及ListView中item的布局文件
ListView布局文件的例子如下:
activity所在的布局XML中只需要含有listview的控件,listview中每一行的item的具体布局则在另一个xml文件中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView android:id="@+id/list_view"
android:layout_height="match_parent"
android:layout_width="match_parent">
</ListView>
</LinearLayout>
ListView的Item的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp"
android:gravity="center_horizontal"
android:textSize="20dp"/>
</LinearLayout>
步骤三 创建一个继承自BaseAdapter的类
例子如下所示:
private class ExampleAdapter extends BaseAdapter{
private LayoutInflater mInflater = null;
private ExampleAdapter(Context context){
this.mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return listItems.size();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return null;
}
}
这里主要需要重写的方法有getcount 和getView 因为在绘制listview的时候需要多次调用getcount方法和getView方法。这里getCount的返回值就是第一步里面定义的listItems大小。同时在这个类里定一个成员变量mInflater和一个构造方法。
layoutInflater的作用
LayoutInflater的作用类似于findviewById() .不同在于LayoutInflater是用来找res/layout下的xml布局文件,并且实例化。
具体作用如下:1 对于一个没有载入或者想要动态载入的界面,都需要使用Layoutinflater.inflater() 来载入。
2 对于已经载入的界面,就可以使用Activity.findViewById()方法来获取其中的界面元素。
获得layoutInflater实例的三种方式
1 layoutinflater inflater = getLayoutInflater();
2 LayoutInflater localinflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)
3 LayoutInflater inflater = LayoutInflater.from(context)
这三种的本质都是调用context.getSystemService()
获得实例之后可以通过实例调用该类的方法inflate 这个方法有一下几种的过载形式,返回值均为View对象.
public View inflate (int resource, ViewGroup root)
public View inflate (XmlPullParser parser, ViewGroup root)
public View inflate (XmlPullParser parser, ViewGroup root, boolean attachToRoot)
public View inflate (int resource, ViewGroup root, boolean attachToRoot)
示例代码如下:
LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
//下面第二个参数可以为Null
View view = inflater.inflate(R.layout.custom, (ViewGroup)findViewById(R.id.test));
//EditText editText = (EditText)findViewById(R.id.content);// error
EditText editText = (EditText)view.findViewById(R.id.content);
步骤四 为ListView 绑定适配器
首先实例化自定义的Adapter,然后找到listview视图的对象,用setAdapter方法为ListVIew绑定适配器。
例子如下:
private ListView listview;
private ExampleAdapter adapter = new ExampleAdapter();
listview.setAdapter(adapter);
步骤五 六 覆盖getView方法
View getView():返回列表项对应的视图,方法体中
1 ◆实例化视图填充器
2 ◆用视图填充器,根据Xml文件,实例化视图
3 ◆根据布局找到控件,并设置属性
4 ◆返回View视图
实例如下:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = new ViewHolder();
if(convertView == null){
convertView = mInflater.inflate(R.layout.item_list_view,null);
viewHolder.textView = (TextView)convertView.findViewById(R.id.list_view_text);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.textView.setText(listItems.get(position));
return convertView;
}
private class ViewHolder{
TextView textView;
}
这里调用自带的convertview ,如果缓存为空 将LayoutInflater的实例赋给convertview,convertview用来存储加载布局(listview的item 的layout)的layout.xml,同时在讲加载布局内的findViewById的值放到viewHoler中。如果convertview不为空,则将findviewById的值取出来。这里就完成了实例化视图以及根据布局查找控件。接下里将存储数据的listItems来给view中的控件设置属性。最后返回view视图。