Listview列表视图的使用讲解
文章目录
Listview的定义
Listview在Android developers开发手册中的定义为:
Displays a vertically-scrollable collection of views, where each view is positioned immediatelybelow the previous view in the list.A list view is an adapter view that does not know the details, such as typeand contents, of the views it contains. Instead list view requestsviews on demand from a ListAdapter as needed, such as to display newviews as the user scrolls up or down.
翻译成中文则为:
显示垂直可滚动的视图集合,其中每个视图都位于列表中上一个视图的紧下方。列表视图是一个适配器视图,它不知道其包含的视图的详细信息,例如类型和内容。相反,列表视图根据需要从中请求视图ListAdapter,例如在用户向上或向下滚动时显示新视图。
通俗理解为当需要开发在一个视图页面中展示多个结构相同的组件时,可以使用listview列表视图要解决问题。
listview的显示需要三个元素
- ListVeiw:用来展示列表的View
- 适配器: 用来把数据映射到ListView上的中介
- 数据源: 具体的将被映射的字符串,图片,或者基本组件
什么是适配器呢?
- 适配器是一个连接数据和AdapterView的桥梁,通过它能有效地实现数据与AdapterView的分离设置,使AdapterView与数据的绑定更加简便,修改更加方便。将数据源的数据适配到ListView中的常用适配器有:ArrayAdapter、SimpleAdapter 和 SimpleCursorAdapter。
ListAdapter
ListAdapter可以作为AbsListView的数据源,AbsListView的子类有ListView、GridView和ExpandableListView。
ListAdapter相比Adapter新增了areAllItemsEnabled和isEnabled两个方法。
SpinnerAdapter
SpinnerAdapter可以作为AbsSpinner的数据源,AbsSpinner的子类有Gallery,
Spinner和AppCompatSpinner。
相比Adapter,SpinnerAdapter中新增了getDropDownView方法,该方法与Adapter接口中定义的getView方法类似,该方法主要是供AbsSpinner调用,用于生成Spinner下拉弹出区域的UI。在SpinnerAdapter的子类BaseAdapter中,getDropDownView方法默认直接调用了getView方法。
ArrayAdapter和SimpleAdapter都重写了getDropDownView方法,这两个类中的getDropDownView方法与其getView的方法都调用了createViewFromResource方法,所以这两个类中方法getView与方法getDropDownView代码基本一致。
CursorAdapter也重写了getView与getDropDownView方法,虽然这两个方法没有使用公共代码,但是这两个方法代码逻辑一致。
综上,我们可知当我们在覆写getDropDownView方法时,应该尽量使其与getView的代码逻辑一致。
BaseAdapter
BaseAdapter主要实现了以下功能:
- BaseAdapter实现了观察者模式,Adapter接口定义了方法registerDataSetObserver和unregisterDataSetObserver,BaseAdapter中维护了一个DataSetObservable类型的变量mDataSetObservable,并实现了方法registerDataSetObserver和unregisterDataSetObserver。
- BaseAdapter重写了getDropDownView方法,其调用了getView方法,如下所示:
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getView(position, convertView, parent);
}
- 覆写其他一些方法,设置了默认值,比如覆写hasStableIds方法,使其默认返回false
ArrayAdapter
- ArrayAdapter的构造函数既可以接收List作为数据源,又可以接收一个数组作为数据源,如果传入的是一个数组,那么在构造函数中也会通过Arrays.asList()将数组转换成list,最终用mObjects存储该list。
- 简而言之,就是用ArrayAdapter可以实现简单的ListView的数据绑定。默认情况下,ArrayAdapter绑定每个对象的toString值到layout中预先定义的TextView控件上。ArrayAdapter的使用非常简单。
SimpleAdapter
- 很多时候需要在列表中展示一些除了文字以外的东西,比如图片等。这时候可以使用SimpleAdapter。SimpleAdapter的使用也非常简单,同时它的功能也非常强大。可以通过它自定义ListView中的item的内容,比如图片、多选框等。
构造方法:
参数解析:
在官方手册中:
讲解:
- context :是要运行simpleadapter关联的view正在运行的上下文
data:为类型为map的list类型的数据
resource:为listview组件所在的layout页面的id
from:为map中的key组成的数组
to:为每一个列表视图所有组件的id组成的数组
公共方法
public int getCount (): //表示的数据集中有多少个项目。
public View getDropDownView (int position,
View convertView,
ViewGroup parent)://获取一个View,它在下拉弹出窗口中显示数据集中指定位置的数据。
public Resources.Theme getDropDownViewTheme ()://返回先前通过调用设置的值
public Filter getFilter ()://返回一个过滤器,该过滤器可用于使用过滤模式约束数据。
public Object getItem (int position)://获取与数据集中指定位置关联的数据项。
public long getItemId (int position)://获取与列表中指定位置关联的行ID。
public View getView (int position,
View convertView,
ViewGroup parent)://获取一个在数据集中指定位置显示数据的视图。
public SimpleAdapter.ViewBinder getViewBinder ()://返回ViewBinder用于将数据绑定到视图的。
public void setDropDownViewResource (int resource)://设置布局资源以创建下拉视图。
public void setDropDownViewTheme (Resources.Theme theme)://设置Resources.Theme针对其放大下拉视图。
public void setViewBinder (SimpleAdapter.ViewBinder viewBinder)://设置用于将数据绑定到视图的绑定器。
public void setViewImage (ImageView v,
int value)://由bindView()调用以设置ImageView的图像,但前提是不存在现有的ViewBinder或现有的ViewBinder无法处理与ImageView的绑定。
public void setViewText (TextView v,
String text)://由bindView()调用以设置TextView的文本,但前提是不存在现有的ViewBinder或现有的ViewBinder无法处理与TextView的绑定。
使用SimpleAdapter基本步骤为:
- 定义一个集合来存放ListView中item的内容;
- 定义一个item的布局文件;
- 创建一个 SimpleAdapter 对象;
- 通过ListView的setAdapter()方法绑定 SimpleAdapter 。
实例如下:
此视图是由一个个水平分布的一个testview组件和一个imageview组成的视图组件,每个视图组件的结构一摸一样,不过具体内容却不一致,此时就可用listview轻松完成。
实例具体实现
<1>在一个xml中定义组件Listview
main.xml
说明:定义一个listivew组件
<?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">
<ListView
android:id="@+id/mylist"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<2>在新一个xml中定义想要试图组件结构
layout.xml
说明:组件结构组件实现为相对布局,左边为一个文本框testview,右边为一个图片imageview
<?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">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:paddingLeft="20dp">
</TextView>
<ImageView
android:id="@+id/image"
android:layout_width="30dp"
android:layout_height="30dp"
android:padding="5dp"
android:layout_alignParentRight="true">
</ImageView>
</RelativeLayout>
<3>放入所需图片资源(若视图组件无另外的资源此步省略)
说明:把图片资源放入res文件夹中的drawable中
<4>在主应用类中编写listview
Mainactivity.java
说明:创建数组存放视图结构的具体属性,如实例中的文本框的text和图片的id,在oncreate方法中setContentview()调用listview所在的xml,然后定义Map<>类型的ArrayList集合,把每一对的值放入map中,在把map加入到list中,然后定义具体的simpleAdapter,加入要使用listview的视图页面中即可
public class MainActivity extends AppCompatActivity {
private String[] names=new String[]{"Lion","Tiger","Monkey","Dog","Cat","Elephant"};
private int[] images = new int[]{R.drawable.lion,R.drawable.tiger,R.drawable.monkey,R.drawable.dog,R.drawable.cat,R.drawable.elephant};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
List<Map<String, Object>> lists = new ArrayList<Map<String, Object>>();
for (int i = 0; i < names.length; i++) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("text",names[i]);
map.put("image",images[i]);
lists.add(map);
}
SimpleAdapter simpleAdapter = new SimpleAdapter(this,lists,R.layout.layout,
new String[]{"text","image"},new int[]{R.id.text,R.id.image});
ListView list = findViewById(R.id.mylist);
list.setAdapter(simpleAdapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast toastCenter = Toast.makeText(getApplicationContext(),names[position],Toast.LENGTH_SHORT);
toastCenter.show();
}
});
}