您的位置:首页 > 移动开发 > Android开发

Android 自定义Adapter的Listview

2013-03-22 16:46 357 查看
在开发中,我们经常使用到ListView这个控件。Android的API也提供了许多创建ListView适配器的快捷方式。例如ArrayAdapter、SimpleAdapter和SimpleCursorAdapter等。但你是否发现,如果采用这些系统自带的适配器,有时候会有局限性。这时,我们一般采取自定义适配器来实现需求。

一,ListView的创建,一般要具备两大元素:

       1)数据集,即要映射的字符串、图片信息之类。

       2)适配器,实现把要映射的字符串、图片信息映射成视图(如Textview、Image等组件),再添加到ListView中。

下面是一个实操例子:

       实现细节:

       1、创建数据集,一般定义如下     
private List<Map<String, Object>> list;

             元素添加方式:

HashMap<String, Object> hashMap = new HashMap<String, Object>();
hashMap.put(key, value);hashMap.put(key, value);list.add(hashMap);


         2、创建适配器


public class ListViewAdapter extends BaseAdapter{........}  //自定义的适配器一般继承BaseAdapter类
listViewAdapter = new ListViewAdapter(this, list);


        3、给ListView设置适配器  
listView.setAdapter(listViewAdapter);


          4、这里还有个关键点,如何把list_item.xml布局作为一个视图,添加到listView中:

LayoutInflater listContainer;   //视图容器工厂
listContainer = LayoutInflater.from(context); //创建视图容器工厂并设置上下文
convertView = listContainer.inflate(R.layout.list_item, null);   //创建list_item.xml布局文件的视图


 listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长度,然后根据这个长度,调用getView()逐一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的布局。我们用LayoutInflater的方法将定义好的main.xml文件提取成View实例用来显示。然后*将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那再绘制下一行,直到绘完为止。在实际的运行过程中会发现listView的每一行没有焦点了,这是因为Button抢夺了listView的焦点,只要布局文件中将Button设置为没有焦点就OK了

二,自定义Adapter

具体要复写的方法有4个:

public int getCount()  方法主要是返回ListView中要显示的子View数量

public Object getItem(int position)  方法是要返回一个子View,即ListView中的一个子条目,当然你也可以自定义返回你想要的信息

public long getItemId(int position) 方法是根据ListView中的位置返回id

b56c
public View getView(int position, View convertView, ViewGroup parent)  

第四个方法主要是返回这个条目的整个信息,它是一个单独的布局文件,当然根据android结构也是一个View类的继承类了,这里还有一个知识点是LayoutInflater类,它的inflate()方法可以根据布局文件获得其View返回值,而最重要的思想是你要从这些条目中获得其子View

还有一个更重要的是其构造方法MyAdapter(Context context, List<Map<String, Object>> list),参数不是固定的,可以根据要用到的数据自己定义,第一个参数是要显示的上下文环境,第二个参数是用来记录各个条目的信息

public class MyAdapter extends BaseAdapter
{
private Context context;
private LayoutInflater layoutInflater;
private List<Map<String, Object>> list;
//构造方法,参数list传递的就是这一组数据的信息
public MyAdapter(Context context, List<Map<String, Object>> list)
{
this.context = context;
layoutInflater = LayoutInflater.from(context);
this.list = list;
}
//得到总的数量
public int getCount()
{
// TODO Auto-generated method stub
return this.list!=null? this.list.size(): 0 ;
}
//根据ListView位置返回View
public Object getItem(int position)
{
// TODO Auto-generated method stub
return this.list.get(position);
}
//根据ListView位置得到List中的ID
public long getItemId(int position)
{
// TODO Auto-generated method stub
return position;
}
//根据位置得到View对象
public View getView(int position, View convertView, ViewGroup parent)
{
if(convertView == null)
{
convertView = layoutInflater.inflate(R.layout.item, null);
}
//得到条目中的子组件
TextView tv1 = (TextView)convertView.findViewById(R.id.nameTextView);
ProgressBar pb = (ProgressBar)convertView.findViewById(R.id.sizeProgressBar);
TextView tv2 = (TextView)convertView.findViewById(R.id.sizeTextView);
//从list对象中为子组件赋值
tv1.setText(list.get(position).get("name").toString());
pb.setProgress(Integer.parseInt(list.get(position).get("size").toString()));
tv2.setText(list.get(position).get("size").toString());
return convertView;
}
}
Android中的自定义Adapter(继承自BaseAdapter)——与系统Adapter的调用方法一致——含ViewHolder显示效率的优化
http://blog.csdn.net/listening_music/article/details/6965755

http://hypercube1024.iteye.com/blog/515830
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android