Android入门--ListView使用总结
2015-03-15 18:01
399 查看
ListView,简单理解成列表显示,目前大多数Android端的应用软件都会使用ListView,可见其在开发中的重要性,所以有必要深入理解掌握,下面开始总结:
首先,需要理解ListView的组成
从图中可以看出一个最简单的ListView的组成:
(1)ListView页面
(2)ListView的每一项
(3) 每一项中的数据
然后是ListView的功能:1,将数据填充到View中,2.响应点击事件
第1点,将数据填充到View中,就需要使用 适配器(Adapter) 来连接ListView和数据,让数据按照给定的布局显示在ListView中
第2点,响应事件事件,一般ListView都会有SetOnItemClickListener方法,用来响应点击事件,或者,在OnClick方法中一般会有参数为点击的item的索引和点击的item的View,只需要简单引用就能找到点击的item项
Adapter的分类:
ArrayAdapter,最简单的Adapter,用来绑定数组型数据
SimpleAdaper,使用最广的Adapter,灵活性高,可根据XML布局文件的不同而适配数据
SimpleCursorAdapter,对数据库操作时用的Adapter,根据从数据库获取到的数据进行适配
BaseAdapter,基础Adapter,需要用其他类来继承它,然后重写getView方法,能得到不同的适配
注:SimpleAdapter和BaseAdapter的区别:BaseAdapter可以实现在单个ListView的Item中添加按钮并实现点击事件,而SimpleAdapter不能对Item中的按钮等交互性控件的事件进行处理,只能对ListView的Item进行SetOnItemClickListener
以上是使用比较广的四种适配器,其实适配器种类还有很多,但是目的都是一样的--将数据和ListView适配,使数据能够在ListView中显示
下面通过代码来实际操作说明
1.通过ArrayAdapter使用ListView
一个最简单的ListView使用方法,使用ArrayAdapter:1).在布局文件中添加ListView标签;2).在代码中初始化ListView,得到实例,然后调用实例的sertAdapter方法,可以在setAdapter中创建匿名内部类Adapter();对于Adapter的设置很重要,因为在Adapter中需要指定显示的View样式和数据源,这样一个最简单的ListView就实现了;
运行效果:
注:Android系统还提供了几种不同样式的item布局,包括带选择框的,带按钮的,各种不同样式,具体情况具体使用吧,我这里使用的是最简单的布局样式,仅显示一行文本
2.通过SimpleAdapter使用ListView
使用SimpleAdapter,首先创建Item布局文件,这是在ListView中单个Item显示的样式,然后在代码中初始化ListView,创建ArrayList<Hashmap<String,Object>>用于绑定数据,每一个Item中的数据将绑定到Hashmap中,这样ArrayList实例调用add方法就能将数据加入,然后创建SimpleAdapter的实例,添加数据和布局,最后调用ListView的SetAdapter方法,添加这个SimpleAdapter就能完成使用
首先是item的布局:
然后是activity_main的布局文件,整个页面就是一个简单的ListView:
最后就是MainActivity中的代码:
注:SimpleAdapter和SimpleCursorAdapter的区别仅仅在于数据源的不同,SimpleCursorAdapter是通过Cursor实例获取到数据库的内容,然后作为数据源传入SimpleCursorAdapter的参数,这里就不做记录
3.通过BaseAdapter使用ListView
使用BaseAdapter,因为BaseAdapter是抽象类,所以需要新建一个类继承自BaseAdapter类,然后调用ListView的SetAdapter时,使用这个新建的类作为参数,在BaseAdapter中需要重写几个方法,其中getView()方法是对View的适配,也是对ListView进行优化的一个关键方法,对于ListView的优化,以下内容来自网络:
第一种:没有任何处理,不建议这样写。如果数据量少看将就,但是如果列表项数据量很大的时候,会每次都重新创建View,设置资源,严重影响性能,所以从一开始就不要用这种方式
第三种ListView优化:通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。
当我们判断 convertView == null 的时候,如果为空,就会根据设计好的List的Item布局(XML),来为convertView赋值,并生成一个viewHolder来绑定converView里面的各个View控件(XML布局里面的那些控件)。再用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。(看下面代码中)
如果convertView不为空的时候,就会直接用convertView的getTag(),来获得一个ViewHolder。
首先创建ListView中的item页面,这里的item页面和之前的SimpleAdapter中的item页面大致相同,只是在右边多加了一个按钮,所以就不贴出来了。
然后是MainActivity中,我这里为了方便是将继承自BaseAdapter类的子类mBaseAdapter写在MainActivity中的,也可以单独建个类文件来写,注意构造方法传参时要传入数据源;
运行效果如图:
以上,简单总结了四种常用的Adapter和ListView结合使用的方法,其中需要重点掌握的是BaseAdapter,虽然看起来比较繁琐,还涉及到什么ListView性能优化,但是实际操作起来,和SimpleAdapter大体相似,多练习几遍,多敲敲代码就能熟练使用,以后还需要继续努力深入学习,加油!
首先,需要理解ListView的组成
从图中可以看出一个最简单的ListView的组成:
(1)ListView页面
(2)ListView的每一项
(3) 每一项中的数据
然后是ListView的功能:1,将数据填充到View中,2.响应点击事件
第1点,将数据填充到View中,就需要使用 适配器(Adapter) 来连接ListView和数据,让数据按照给定的布局显示在ListView中
第2点,响应事件事件,一般ListView都会有SetOnItemClickListener方法,用来响应点击事件,或者,在OnClick方法中一般会有参数为点击的item的索引和点击的item的View,只需要简单引用就能找到点击的item项
Adapter的分类:
ArrayAdapter,最简单的Adapter,用来绑定数组型数据
SimpleAdaper,使用最广的Adapter,灵活性高,可根据XML布局文件的不同而适配数据
SimpleCursorAdapter,对数据库操作时用的Adapter,根据从数据库获取到的数据进行适配
BaseAdapter,基础Adapter,需要用其他类来继承它,然后重写getView方法,能得到不同的适配
注:SimpleAdapter和BaseAdapter的区别:BaseAdapter可以实现在单个ListView的Item中添加按钮并实现点击事件,而SimpleAdapter不能对Item中的按钮等交互性控件的事件进行处理,只能对ListView的Item进行SetOnItemClickListener
以上是使用比较广的四种适配器,其实适配器种类还有很多,但是目的都是一样的--将数据和ListView适配,使数据能够在ListView中显示
下面通过代码来实际操作说明
1.通过ArrayAdapter使用ListView
一个最简单的ListView使用方法,使用ArrayAdapter:1).在布局文件中添加ListView标签;2).在代码中初始化ListView,得到实例,然后调用实例的sertAdapter方法,可以在setAdapter中创建匿名内部类Adapter();对于Adapter的设置很重要,因为在Adapter中需要指定显示的View样式和数据源,这样一个最简单的ListView就实现了;
package com.example.testarrayadapter; import android.os.Bundle; import android.app.Activity; import android.widget.ArrayAdapter; import android.widget.ListView; public class MainActivity extends Activity { // 定义数据源 private String[] data = { "test01", "test02", "test03", "test04", "test05", "test06" }; // 申明ListView private ListView list = null; // 申明适配器,Adapter中的数据是String类型的 private ArrayAdapter<String> mArrayAdapter = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 绑定控件 list = (ListView) findViewById(R.id.lv); // 创建新的ArrayAdapter,参数需要 // 1,上下文对象 // 2.XML布局文件,这里为了方便,使用的是系统自带的simple_list_item_1布局文件 // 3.最后就是数据源 mArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, data); // 然后执行绑定适配器的操作,这样ListView就和数据进行了绑定 list.setAdapter(mArrayAdapter); // 设置选择模式,这是在使用了带选择框的item布局时,可以通过设置设个属性来设置单选或者多选模式 list.setChoiceMode(ListView.CHOICE_MODE_SINGLE); } }
运行效果:
注:Android系统还提供了几种不同样式的item布局,包括带选择框的,带按钮的,各种不同样式,具体情况具体使用吧,我这里使用的是最简单的布局样式,仅显示一行文本
2.通过SimpleAdapter使用ListView
使用SimpleAdapter,首先创建Item布局文件,这是在ListView中单个Item显示的样式,然后在代码中初始化ListView,创建ArrayList<Hashmap<String,Object>>用于绑定数据,每一个Item中的数据将绑定到Hashmap中,这样ArrayList实例调用add方法就能将数据加入,然后创建SimpleAdapter的实例,添加数据和布局,最后调用ListView的SetAdapter方法,添加这个SimpleAdapter就能完成使用
首先是item的布局:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/IV_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="2dp" android:layout_marginTop="2dp" android:background="#dd3344" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/TV_item_top" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/TV_item_top" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginTop="2dp" android:layout_toRightOf="@+id/IV_item" android:background="#eedd33" android:gravity="center" android:textSize="20sp" /> <TextView android:id="@+id/TV_item_center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/IV_item" android:layout_alignLeft="@+id/TV_item_top" android:layout_alignParentRight="true" android:layout_below="@+id/TV_item_top" android:layout_marginBottom="2dp" android:background="#23ed43" android:gravity="center" android:textSize="14sp" /> </RelativeLayout>
然后是activity_main的布局文件,整个页面就是一个简单的ListView:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <ListView android:id="@+id/LV_simple" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" > </ListView> </RelativeLayout>
最后就是MainActivity中的代码:
package com.example.testsimpleadapter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { // 申明ListView private ListView mListView = null; // 申明SimpleAdapter private SimpleAdapter mSimpleAdapter = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化ListView mListView = (ListView) findViewById(R.id.LV_simple); // 初始化SimpleAdapter,参数为: // 1.上下文对象 // 2.数据源,这里将数据源封装在下面的方法getData中 // 3.布局文件,这里的布局文件就是之前做好的item布局文件 // 4.对应HashMap中的键,用一个String型数组来封装 // 5.对应的布局文件中的控件的id,用一个int型数组来封装 mSimpleAdapter = new SimpleAdapter(this, getData(), R.layout.list_item, new String[] { "icon", "topText", "centerText" }, new int[] { R.id.IV_item, R.id.TV_item_top, R.id.TV_item_center }); // 对ListView设置适配器 mListView.setAdapter(mSimpleAdapter); // 设置ListView的每一项点击事件 mListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // onItemClick事件中的参数: // arg0,Adapter的View,不太清楚,具体还需要再研究 // arg1,点击的item界面的View,就是一个list_item界面,所以可以通过这里获取到控件中的内容 // arg2,点击的item的索引,就是,点击的是第几个item // 这里可以看到,通过arg1就可以获取到点击的那个item界面的TextView控件,然后就能获取到控件上的内容 TextView itemContent = (TextView) arg1 .findViewById(R.id.TV_item_top); Toast.makeText(MainActivity.this, "你点击了 item " + arg2 + "内容是:" + itemContent.getText(), Toast.LENGTH_SHORT).show(); } }); } /** * 获取数据源的方法 */ private List<Map<String, Object>> getData() { List<Map<String, Object>> list_item = new ArrayList<Map<String, Object>>(); for (int i = 0; i < 10; i++) { // 这里一定要注意,每次向list_item中添加的item_data必须是新建的HashMap实例 // 也就是必须每次新建,每次添加,而不能一次新建循环添加 // 所以这个new 语句必须放在for循环内 Map<String, Object> item_data = new HashMap<String, Object>(); item_data.put("icon", R.drawable.ic_launcher); item_data.put("topText", "Top test " + i); item_data.put("centerText", "simpleAdapter center " + i); list_item.add(item_data); } return list_item; } }运行效果图:
注:SimpleAdapter和SimpleCursorAdapter的区别仅仅在于数据源的不同,SimpleCursorAdapter是通过Cursor实例获取到数据库的内容,然后作为数据源传入SimpleCursorAdapter的参数,这里就不做记录
3.通过BaseAdapter使用ListView
使用BaseAdapter,因为BaseAdapter是抽象类,所以需要新建一个类继承自BaseAdapter类,然后调用ListView的SetAdapter时,使用这个新建的类作为参数,在BaseAdapter中需要重写几个方法,其中getView()方法是对View的适配,也是对ListView进行优化的一个关键方法,对于ListView的优化,以下内容来自网络:
第一种:没有任何处理,不建议这样写。如果数据量少看将就,但是如果列表项数据量很大的时候,会每次都重新创建View,设置资源,严重影响性能,所以从一开始就不要用这种方式
@Override public View getView(int position, View convertView, ViewGroup parent) { View item = mInflater.inflate(R.layout.list_item, null); ImageView img = (ImageView)item.findViewById(R.id.img) TextView title = (TextView)item.findViewById(R.id.title); TextView info = (TextView)item.findViewById(R.id.info); img.setImageResource(R.drawable.ic_launcher); title.setText("Hello"); info.setText("world"); return item; }第二种ListView优化:通过缓存convertView,这种利用缓存contentView的方式可以判断如果缓存中不存在View才创建View,如果已经存在可以利用缓存中的View,提升了性能
public View getView(int position, View convertView, ViewGroup parent) { if(convertView == null) { convertView = mInflater.inflate(R.layout.list_item, null); } ImageView img = (ImageView)convertView.findViewById(R.id.img) TextView title = (TextView)convertView.findViewById(R.id.title); TextView info = (TextView)ConvertView.findViewById(R.id.info); img.setImageResource(R.drawable.ic_launcher); title.setText("Hello"); info.setText("world"); return convertView; }
第三种ListView优化:通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。
当我们判断 convertView == null 的时候,如果为空,就会根据设计好的List的Item布局(XML),来为convertView赋值,并生成一个viewHolder来绑定converView里面的各个View控件(XML布局里面的那些控件)。再用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。(看下面代码中)
如果convertView不为空的时候,就会直接用convertView的getTag(),来获得一个ViewHolder。
//在外面先定义,ViewHolder静态类 static class ViewHolder { public ImageView img; public TextView title; public TextView info; } //然后重写getView @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if(convertView == null) { holder = new ViewHolder(); convertView = mInflater.inflate(R.layout.list_item, null); holder.img = (ImageView)item.findViewById(R.id.img) holder.title = (TextView)item.findViewById(R.id.title); holder.info = (TextView)item.findViewById(R.id.info); convertView.setTag(holder); }else { holder = (ViewHolder)convertView.getTag(); holder.img.setImageResource(R.drawable.ic_launcher); holder.title.setText("Hello"); holder.info.setText("World"); } return convertView; }下面是实例:
首先创建ListView中的item页面,这里的item页面和之前的SimpleAdapter中的item页面大致相同,只是在右边多加了一个按钮,所以就不贴出来了。
然后是MainActivity中,我这里为了方便是将继承自BaseAdapter类的子类mBaseAdapter写在MainActivity中的,也可以单独建个类文件来写,注意构造方法传参时要传入数据源;
package com.example.testbaseadapter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { // 申明ListView实例 private ListView mListView = null; // 申明一个mBaseAdapter类的实例 private mBaseAdapter mAdapter = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 绑定ListView实例 mListView = (ListView) findViewById(R.id.LV_show); // 初始化mBaseAdapter实例 mAdapter = new mBaseAdapter(this); // 设置ListView实例的适配器 mListView.setAdapter(mAdapter); } /** * 获取数据的方法,这个和之前的SimpleAdapter一样,就不再赘述 */ private List<Map<String, Object>> getData() { List<Map<String, Object>> list_item = new ArrayList<Map<String, Object>>(); for (int i = 0; i < 10; i++) { Map<String, Object> item_data = new HashMap<String, Object>(); item_data.put("icon", R.drawable.ic_launcher); item_data.put("topText", "TopText " + i); item_data.put("centerText", "this is centerText " + i); list_item.add(item_data); } return list_item; } /** * 新建一个类mBaseAdapter继承自BaseAdapter * */ class mBaseAdapter extends BaseAdapter { private LayoutInflater mInflater; private Context mContext; // 构造方法,根据Context加载布局 public mBaseAdapter(Context context) { mContext = context; mInflater = LayoutInflater.from(mContext); } // 获取数量,通过返回getData()的大小表示获取的数量 @Override public int getCount() { return getData().size(); } // 获取getData()中与指定索引对应的数据项 @Override public Object getItem(int position) { return position; } // 获取在列表中与指定索引对应的行id @Override public long getItemId(int position) { return position; } // 这里是最重要的方法,ListView的优化也在这里进行 @Override public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder holder; // 如果缓存convertView为空,则需要创建View if (convertView == null) { // 为新建的convertView绑定布局 convertView = mInflater.inflate(R.layout.list_item, null); holder = new ViewHolder(); // 绑定各组件 holder.imageView = (ImageView) convertView .findViewById(R.id.IV_item); holder.topTextView = (TextView) convertView .findViewById(R.id.TV_item_top); holder.centerTextView = (TextView) convertView .findViewById(R.id.TV_item_center); holder.clickButton = (Button) convertView .findViewById(R.id.BT_item); // 将设置好的布局保存到缓存中,并将其设置在Tag里,以便后面方便取出Tag convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } // 对组件元素进行设置,比如设置在组件中要显示的内容 holder.imageView.setImageResource(R.drawable.ic_launcher); holder.topTextView.setText(getData().get(position).get("topText") .toString()); holder.centerTextView.setText(getData().get(position) .get("centerText").toString()); //按钮的点击事件 holder.clickButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //这里获取到点击的item的position,并Toast显示 Toast.makeText(mContext, "你点击了id=" + getItemId(position), Toast.LENGTH_LONG).show(); } }); return convertView; } } // ViewHolder静态类 public static class ViewHolder { public ImageView imageView; public TextView topTextView; public TextView centerTextView; public Button clickButton; } }
运行效果如图:
以上,简单总结了四种常用的Adapter和ListView结合使用的方法,其中需要重点掌握的是BaseAdapter,虽然看起来比较繁琐,还涉及到什么ListView性能优化,但是实际操作起来,和SimpleAdapter大体相似,多练习几遍,多敲敲代码就能熟练使用,以后还需要继续努力深入学习,加油!
相关文章推荐
- Android ListView 入门知识--各种 Adapter 配合使用
- Android ListView入门知识--各种Adapter配合使用
- android编程之ExpandableListView使用总结
- android listview使用总结
- Android ListView 常见问题与使用总结
- Android ListView 入门知识--各种 Adapter 配合使用
- 布局文件Android ListView入门知识--各种Adapter配合使用
- android ListView组件使用常见问题或形式总结(一)
- Android ListView入门知识--各种Adapter配合使用
- Android入门--WebView使用总结
- Android关于ListView的总结--使用ListActivity
- Android ListView入门知识--各种Adapter配合使用
- Android ListView入门知识--各种Adapter配合使用
- 无废话Android之listview入门,自定义的数据适配器、采用layoutInflater打气筒创建一个view对象、常用数据适配器ArrayAdapter、SimpleAdapter、使用ContentProvider(内容提供者)共享数据、短信的备份、插入一条记录到系统短信应用(3)
- Android ListView入门知识--各种Adapter配合使用 (转)
- Android ListView入门知识--各种Adapter配合使用
- android编程之ExpandableListView使用总结
- Android ListView入门知识--各种Adapter配合使用
- Android入门--ViewPager使用总结
- Android----ListView入门知识--各种Adapter配合使用