ListView是android最常用的控件之一,允许用户通过手指上下滑动的方式将屏幕外的数据滚动到屏幕内,同时屏幕上原有的数据将滚动出屏幕,例如可用于显示联系人信息,系统设置等。
有以下两种方式实现ListView:
下面分别介绍。
在activity_main.xml中添加如下代码:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:headerDividersEnabled="false"
android:listSelector="#001166"
android:divider="#ff00ff"
android:dividerHeight="1dp"
/>
</RelativeLayout>
其中几个重要的属性:
修改好布局文件之后,我们来修改一下对应的activity代码:
/**ListView练习
* @author sywyg
* @time 2015/4/12
*/
public class MainActivity extends Activity implements AdapterView.OnItemClickListener{
private ListView lv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView)findViewById(R.id.list_view);
String[] cities = {"南京","北京","上海","广州","深圳","徐州","丰县"};
/**
* ArrayAdapter参数
* 1. 当前上下文Context对象
* 2. ListView子项布局的id
* 3. 需要适配的数组
*
*/
/*ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,names);
//设置选项为单选
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_single_choice,names);
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
//设置选项为多选
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_multiple_choice,cities);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);*/
//获取适配器
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,cities);
//绑定适配器
lv.setAdapter(adapter);
//事件监听
lv.setOnItemClickListener(this);
}
/**
* @param adapterView 当前ListView
* @param view 选中的视图可能是控件也可能是布局
* @param position 选中的第几个
* @param id 选中的id
*/
@Override
public void onItemClick(AdapterView<?> adapterView, View view,int position, long id){
ListView listView = (ListView)adapterView;
//判断是选中还是撤销选择
boolean ischecked = listView.isItemChecked(position);
listView.setSelection(position);
if(ischecked){
Toast.makeText(this, ((TextView) view).getText().toString(), Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(this, "撤销选择", Toast.LENGTH_SHORT).show();
}
}
}
在onCreate()
中我们首先创建了适配器对象ArrayAdapter实例,其中的ListView子项布局的id参数为系统提供的布局文件,其实我们完全可以自己定义,这个后续介绍。接着调用ListView的setAdapter()
方法,设置适配器对象。最后,我们也设置了ListView的点击事件(实现AdapterView.OnItemClickListener,并覆盖onItemClick()
)。
我们这里使用了ArrayAdapter适配器,下面我们使用SimpleAdapter适配器实现图文并茂。
SimpleAdapter适配器需要一个额外的布局文件,来配置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="horizontal">
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
这里包含两个控件,对应图片和文本。
而对于主xml仍然只有ListView控件,这里不再给出。
SimpleAdapter实例化需要接收五个参数,分别为:
下面给出了一个简单的代码:
// 1.添加ListView选项,每个选项为图片和文字
Map<String,Object> item1 = new HashMap<String, Object>();
item1.put("image",R.drawable.abc_ab_share_pack_mtrl_alpha);
item1.put("name","sywyg");
Map<String,Object> item2 = new HashMap<String, Object>();
item2.put("image",R.drawable.abc_btn_check_material);
item2.put("name","wyg");
//Map列表项添加到List中
List< Map<String,Object>> list = new ArrayList< Map<String,Object>>();
list.add(item1);
list.add(item2);
// 2.映射关系
String[] from = {"image","name"};
int[] to = {R.id.iv,R.id.tv};
// 3.设置适配器,参数上面有说明
SimpleAdapter simpleAdapter = new SimpleAdapter(this,list,R.layout.item,from,to);
通过上面的处理,就创建了一个SimpleAdapter对象,接着调用ListView的setAdapter()
方法。最后,设置ListView的点击事件(和上面的方法一样)。
虽然可以通过SimpleAdapter实现图文并茂,但是想要实现更复杂的布局,我们需要实现自定义的适配器,我们可以继承ArrayAdapter,SimpleAdapter,BaseAdapter,这里我们选择继承BaseAdapter抽象类。
实现代码如下:
public class MyAdapter<T> extends BaseAdapter {
private List<T> mObjects;
private Context mContext;
private int resource;
public MyAdapter(Context context,int resource,List<T> Objects) {
super();
mContext = context;
this.resource = resource;
mObjects = Objects;
}
// 获取列表项的总数
@Override
public int getCount() {
return mObjects.size();
}
//获取列表项
@Override
public Object getItem(int position) {
return mObjects.get(position);
}
//获取列表项id
@Override
public long getItemId(int position) {
return position;
}
/**
* 返回子视图,在每个子项被滚动到屏幕内的时候会被调用
* @param position 选中的位置
* @param convertView 转换视图,用于将之前加载好的布局进行缓存
* 通过它来优化ListView,提高性能
* @param parent 父组件
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
ViewHolder viewHolder = null;
if(convertView == null) {
// 获取显示ListView子项的布局
view = LayoutInflater.from(mContext).inflate(resource, null);
// 获取子布局中的控件
viewHolder.iv = (ImageView) view.findViewById(R.id.iv);
viewHolder.tv = (TextView) view.findViewById(R.id.tv);
// 将ViewHolder对象保存在tag中
view.setTag(viewHolder);
} else{
// 避免在每次调用该方法时重新加载布局
view = convertView;
// 取出ViewHolder对象
viewHolder = (ViewHolder)view.getTag();
}
// 获取position位置的选项
City city = (City)mObjects.get(position);
// 设置控件值
viewHolder.iv.setImageResource(city.getImage());
viewHolder.tv.setText(city.getName());
return view;
}
/**
* 缓存控件的实例,避免多次实例化控件
*/
static class ViewHolder{
ImageView iv;
TextView tv;
}
}
继承BaseAdapter抽象类需要实现以上4个方法,另外在构造器中将上下文,ListView子布局id和数据传递进来。下面我们来重点讲一下getView()
方法。
getView()
用于返回视图,在每个子项被滚动到屏幕内的时候会被调用(首次调用次数为屏幕能够显示子项的个数,当然ListView的宽高是确定的,否则还是会反复调用确定宽高),position值从0到屏幕能够显示的最大列表项数减1进行循环(屏幕上显示的最大个数应该是正好显示个数加1)。在其中,转换视图convertView用于将之前加载好的且目前没有显示在屏幕上的一个子布局进行缓存(当position到达最大值之后在向下滑动,就会缓存第0个),通过它来优化ListView,提高性能,然后通过一个内部类ViewHolder缓存布局控件,避免每次加载视图时调用findViewById()
。
创建好适配器类之后,我们同样通过刚才的方法在Activity处理ListView,只不过现在使用的适配器是我们自定义的适配器。代码不再给出。
我们也可以通过继承ListActivity实现ListView,这种方法不需要我们提供ListView视图,只需设置适配器,监听器也可以通过该类的方法,如下:
public class ListActivityTest extends ListActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//创建适配器
String[] cities = {"南京","北京","上海","广州","深圳","徐州","丰县"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_2,cities);
//获得该activity的ListView
//ListView listView = getListView();
//设置ListView适配器
setListAdapter(adapter);
}
/**
* ListView事件监听,或者通过继承AdapterView.OnItemClickListener
* 各参数和AdapterView.OnItemClickListener的方法onItemClick对应的一样。
* @param l
* @param v
* @param position
* @param id
*/
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
TextView textView = (TextView)v;
Toast.makeText(this,textView.getText().toString(),Toast.LENGTH_SHORT).show();
}
}
这种不需要我们配置布局,而是利用ListActivity提供的布局,当然我们也可以提供一个,但是必须包含一个id为android:id="@android:id/list"
的ListView控件。
getView()
。findViewById()
,提高了性能。设置ViewHolder为static,只会在第一次加载时会耗费较长的时间,同时保证了内存中只有一个ViewHolder,节省了内存的开销。版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/wangyongge85/article/details/47357321