写在前面的话
1、参考自网络。
2、内容如果有不对的,希望可以指出或补充。
3、巩固内容。
一、概述
ListView(列表视图):是Android中最重要的组件之一,以垂直列表的方式列出所需的列表项。通过适配器
将数据源与展示控件绑定起来(这是适配器视图的共同特征,ListView继承自AbsListView-抽象列表视图,而其又继承了AdapterView-适配器视图)。
用于展示大量数据。
ListView中的常用适配器有:ArrayAdapter(数组适配器-最简单,可展示单行文本
)、SimpleAdapter(简单适配器-可自定义各式布局)和SimpleCursorAdapter(简单游标适配器-可把数据库内容以列表形式展示出来)、BaseAdapter(基适配器-可自定义,继承于它的自定义适配器类)。
二、使用
都需要自定义一个主布局文件(有ListView控件)。
(一)基于ArrayAdapter
无需自定义item布局文件,使用系统提供的布局即可。
//获取到.xml文件中(主布局文件,带有ListView控件的)的ListView控件
ListView testListView1 = findViewById(R.id.test_listView1);
/**1、定义数组来存放ListView中item(条目)内容*/
String [] datas = {"🍎","🍌","🍊","🍑","🍇","🍈","🍒","🍓","🍋",
"🍎","🍌","🍊","🍑","🍇","🍈","🍒","🍓","🍋"};
/**2、通过实现ArrayAdapter的构造方法创建一个ArrayAdapter对象*/
ArrayAdapter arrayAdapter = new ArrayAdapter(
this, //参数1:上下文对象
//参数2:ListView每一行(item)的布局资源id
android.R.layout.simple_list_item_multiple_choice,//系统提供的布局文件(.xml)
datas //参数3:ListView的数据源(数组或数组列表)
);
//补充内容-ListView本身带有单选和多选功能
testListView1.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);//多选
/**3、通过ListView的setAdapter()方法绑定ArrayAdapter*/
testListView1.setAdapter(arrayAdapter);
/**4、使用setOnItemClickListener()为ListView注册条目单击监听器*/
testListView1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//补充内容-判断是否勾选了对应条目
if(testListView1.isItemChecked(position)){
//提示文本
Toast.makeText(TestActivity3.this, "选择了【" + datas[position] + "】",
Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(TestActivity3.this, "取消选择了【" + datas[position] + "】",
Toast.LENGTH_SHORT).show();
}
}
});
运行效果如下。
(二)基于SimpleAdapter
需要自定义item布局文件。
//获取到.xml文件中(主布局文件,带有ListView控件的)的ListView控件
ListView testListView1 = findViewById(R.id.test_listView1);
/**1、定义一个集合来存放ListView中item内容*/
List list = new ArrayList<>();
for(int i = 0; i < 5; i++) {
Map map = new HashMap();
map.put("name", "水果" + i);
map.put("test", "test_" + i);
list.add(map);
}
/**2、定义一个item的.xml布局文件*/
/**3、创建一个SimpleAdapter对象*/
SimpleAdapter adapter = new SimpleAdapter(
this, //参数1:上下文对象(环境)
list, //参数2:数据源,一般为List集合对象
R.layout.list_view_item, //参数3:自定义的item的布局文件
new String[] { "name", "test" }, //参数4:数据源中Map的key组成的一个String数组的字段名称
new int[] {R.id.name, R.id.test} //参数5:自定义的item布局文件中每个控件的对应的id
);
/**4、通过ListView的setAdapter()方法绑定SimpleAdapter*/
testListView1.setAdapter(adapter);
(三)基于BaseAdapter
需要创建自定义适配器(继承自BaseAdapter),且须实现四个抽象方法:getCount()、getItem()、getItemId()、getView()。
1 步骤展示
数据源-自定义实体类
展示-主布局略(里面需要有ListView控件)
TestActivity3.java
package com.example.test;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class TestActivity3 extends Activity {
private ListView testListView1;//展示
private MyAdapter myAdapter;//桥梁
private List<Fruit> fruits;//数据源
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test2_2);
//获取控件
TextView testCheckAll = findViewById(R.id.test_checkAll);
testCheckAll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (testCheckAll.getText().equals("全选")) {
myAdapter.checkAll();//调用对应方法
testCheckAll.setText("取消全选");
} else{
myAdapter.noCheckAll();
testCheckAll.setText("全选");
}
}
});
//获取ListView控件
testListView1 = findViewById(R.id.test_listView1);
/**1、定义集合来存放ListView中item的内容*/
fruits = getFruits();
/**2、定义一个item的布局文件*/
/**3、定义一个继承了BaseAdapter的子类MyAdapter,重写未实现的方法*/
myAdapter = new MyAdapter(this,fruits);//创建水果适配器
/**4、通过ListView的setAdapter()方法绑定自定义的MyAdapter对象*/
testListView1.setAdapter(myAdapter);
/**5、使用setOnItemClickListener()为ListView注册条目单击监听器*/
testListView1.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//获取数据源
Fruit fruit = fruits.get(position);
//提示文本
Toast.makeText(TestActivity3.this,
"这是【" + fruit.getName() + "】,喜欢就勾选它吧",
Toast.LENGTH_SHORT).show();
}
});
}
private List<Fruit> getFruits() {
//创建联系人列表
List<Fruit> fruits = new ArrayList<>();
Fruit fruit = null;
//创建第1个水果
fruit = new Fruit(R.drawable.img1,"香蕉");
fruits.add(fruit);
//创建第2个水果
fruit = new Fruit(R.drawable.img2,"葡萄");
fruits.add(fruit);
//创建第3个水果
fruit = new Fruit(R.drawable.img3,"火龙果");
fruits.add(fruit);
//创建第4个水果
fruit = new Fruit(R.drawable.img4,"车厘子");
fruits.add(fruit);
//返回水果列表
return fruits;
}
}
TestActivity3.java中提到的第二步:定义一个item的布局文件
MyAdapter.java—TestActivity3.java中提到的第三步:定义一个继承了BaseAdapter的子类MyAdapter,重写未实现的方法
package com.example.test;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**3、定义一个继承了BaseAdapter的子类MyAdapter,重写未实现的方法*/
public class MyAdapter extends BaseAdapter {
private Context context; //上下文
private List<Fruit> fruits; //水果列表
//构造方法
public MyAdapter(Context context, List<Fruit> fruits) {
this.context = context;
this.fruits = fruits;
}
//多选框全选、取消全选
public void checkAll(){
for(Fruit fruit:fruits){
fruit.isCheck = true;
}
notifyDataSetChanged();//必有
}
public void noCheckAll(){
for(Fruit fruit:fruits){
fruit.isCheck = false;
}
notifyDataSetChanged();//必有
}
@Override
//列表项(item)个数
public int getCount() {
return fruits.size();
}
@Override
//获取列表项
public Object getItem(int position) {
return fruits.get(position);
}
@Override
//列表项标识
public long getItemId(int position) {
return position;
}
@Override
//获取列表项视图;转换视图
public View getView(int position, View convertView, ViewGroup parent) {
//声明视图容器
ViewHolder viewHolder;
if (convertView == null) {
//利用布局填充器将自定义的item布局填充转换成视图
convertView = LayoutInflater.from(context).inflate(R.layout.list_view_item,null);
//创建视图容器
viewHolder = new ViewHolder();
viewHolder.testImg = convertView.findViewById(R.id.test_img);
viewHolder.testText = convertView.findViewById(R.id.test_text);
viewHolder.testCheck = convertView.findViewById(R.id.test_check);
//将视图容器附加到转换视图中
convertView.setTag(viewHolder);
}else{
//直接获取到视图容器
viewHolder = (ViewHolder) convertView.getTag();
}
//获取item要显示的Fruit数据
Fruit fruit = fruits.get(position);
//转换视图里的控件
viewHolder.testImg.setImageResource(fruit.getImageId());
viewHolder.testText.setText(fruit.getName());
/**checkbox*/
viewHolder.testCheck.setChecked(fruit.isCheck);//选中状态
viewHolder.testCheck.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(v.isCheck){
fruit.isCheck = false;
}else{
fruit.isCheck = true;
}
}
});
//返回转换的视图
return convertView;
}
//视图容器-提升ListView的运行效率
private static class ViewHolder{
ImageView testImg;
TextView testText;
CheckBox testCheck;
}
}
注意更改一下清单文件中的activity android:name=".TestActivity3">,运行效果如下。
三、补充
2、布局与控件(八)-ListView知多少(下)ChoiceMode详解
3、android listview里包含组件(checkbox)点击事件和Item的点击事件冲突—>解决了遇到的问题-条目点击无效