UI组件之AdapterView及其子类(一)三种Adapter适配器填充ListView
最后更新于:2022-04-01 16:14:02
AdapterView的内容一般是包含多项相同格式资源的列表,常用的有5种AdapterView的子类:
(1)ListView:简单的列表
(2)Spinner:下拉列表,给用户提供选择
(3)Gallery:缩略图,已经被水平的ScrollView和ViewPicker取代,但也还算常用,是一个可以把子项以中心锁定,水平滚动的列表
(4)GridView:网格图,以表格形式显示资源,可以左右滑动的
这里先介绍最简单的显示列表视图ListView。
列表的显示需要三个元素:
1.ListVeiw (或另外三个):用来展示列表的View。
2.Adapter适配器 :用来把数据映射到ListView上的中介,列表项的数据由Adapter提供
3.数据 :具体的将被映射的字符串,图片,或者基本组件。
根据列表的适配器类型,列表分为4种:
(1)ArrayAdapter:它只能处理列表项内容全是文本的情况。
◆数据源:数组或者List<String>对象或者其他
(2)SimpleAdapter: 它不仅可以处理列表项全是文本的情况,当列表项中还有其他控件时,同样可以处理,每个列表项可以定制更复杂的布局,组件等
◆数据源:只能为List<Map<“键”,“值”>>形式的数据
(3)自定义Adapter:继承BaseAdapter,根据xml文件中定义的样式惊醒列表项的填充,适用性最强。
(4)SimpleCursorAdapter:专门用于把游标Cursor(数据库查询集)中的数据映像到列表中(我们以后再来研究),用在SQLite数据库较多
LisView组件常用的Xml属性:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9ab65149.jpg)
android:divider:设置List列表项的分隔条,即可用颜色区分,也可用Drawable对象分隔
android:dividerHeight:设置分隔条高度
**android:entries:指定一个数组资源,Android将根据该数据资源来生成ListView**
**一,使用android:entries属性为LisView指定数组**
~~~
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/listView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:divider="#f00"
android:dividerHeight="2dp"
android:entries="@array/books"
android:headerDividersEnabled="false" >
</ListView>
</LinearLayout>
~~~
arrays.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="books">
<item>北京</item>
<item>上海</item>
<item>广州</item>
<item>深圳</item>
</string-array>
</resources>
~~~
上面一个ListView指定一个 android:entries="@array/books",使用了下面的数组资源
使用数组创建LisView十分简单,但这种LisView能定制的内容很少,甚至连每个列表项的字号,颜色都不能改变
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9ab7d70c.jpg)
**二,使用ArrayAdapter创建LisView**
其中以ArrayAdapter最为简单,**只能展示一行字**
ArrayAdapter的三个参数
* Context:代表访问整个Android应用的接口。几乎创建所有的组件都需要传入Context对象
* textViewResourcedId:一个资源Id,该Id代表一个TextView,该TextView组件将作为AarryAdapter的列表组件,**这里的布局文件是指每个列表项的布局文件,可以自己定制,也可以使用android提供的布局文件**
* **数组或List**:负责为多个列表框提供数据
main.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- 使用红线分隔 -->
<ListView
android:id="@+id/listView1"
android:layout_width="fill_parent"
android:layout_height="335dp"
android:divider="#f00"
android:dividerHeight="2dp"
android:headerDividersEnabled="false" >
</ListView>
<!-- 使用绿线分隔 -->
<ListView
android:id="@+id/listView2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:divider="#0f0"
android:dividerHeight="2dp"
android:headerDividersEnabled="false" >
</ListView>
</LinearLayout>
~~~
array_item.xml 可以定制TextView的字体颜色了
~~~
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shadowColor="#f0f"
android:shadowDx="4"
android:shadowDy="4"
android:shadowRadius="2"
android:textSize="20dp" />
~~~
checked_item.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/TextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20dp"
android:checkMark="@drawable/ok"
android:shadowColor="#f0f"
android:shadowDx="4"
android:shadowDy="4"
android:shadowRadius="2"/>
~~~
MainActivity.java
~~~
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView list1=(ListView) findViewById(R.id.listView1);
ListView list2=(ListView) findViewById(R.id.listView2);
String[] str1={"唐僧","孙悟空","猪八戒","沙和尚"};
//用数组包装ArrayAdapter
/*ArrayAdapter的三个参数
* Context:代表访问整个Android应用的接口。几乎创建所有的组件都需要传入Context对象
* textViewResourcedId:一个资源Id,该Id代表一个TextView,该TextView组件将作为AarryAdapter的列表组件
*
* 数组或List:负责为多个列表框提供数据*/
ArrayAdapter<String> ad1=new ArrayAdapter<String>(this,R.layout.array_item,str1);
//为ListView设置adapter
list1.setAdapter(ad1);
String[] str2={"湖北省","湖南省","江苏省","浙江省"};
//用数组包装ArrayAdapter
ArrayAdapter<String> ad2=new ArrayAdapter<String>(this,R.layout.checked_item,str2);
//为ListView设置adapter
list2.setAdapter(ad2);
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9ab8e86f.jpg)
ArrayAdapter(Context context, int textViewResourceId, List<T> objects)来装配数据,要装配这些数据就需要一个连接ListView视图对象和数组数据的适配器来两者的适配工作,同时用setAdapter()完成适配的最后工作
**三,使用SimpleAdapter创建ListView**
simpleAdapter的扩展性最好,**每个列表项可以定义各种各样的布局出来,可以放上ImageView(图片),还可以放上Button(按钮),CheckBox(复选框)**等等。
simpleAdapter的数据源:只能为List<Map<“键”,“值”>>形式的数据
SimpleAdapter对象,需要5个参数,后面4个是关键
* 第2个参数:是一个List<Map<? extends Map<string,?>>的集合对象,集合中的每个 Map<string,?>对象是一个列表项
* 第3个参数:该参数指定一个列表项布局界面的ID。
* 第4个参数:一个String[]类型的参数,决定提取Map对象中的那些key值对应的value类生成类表项 就是:**需要显示value的key值**
* 第5个参数:int[]类型的参数,决定填充哪些 组件,**就是使用显示值得组件Id**
* 注意:第4,5个参数的数组需要一一对应才行
使用SimpleAdapter提供列表项
main.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="vertical" >
<!-- 定义一个ListView -->
<ListView
android:id="@+id/listView1"
android:layout_width="fill_parent"
android:layout_height="255dp" >
</ListView>
<TextView
android:id="@+id/textView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.00"
android:textColor="#f0f"
android:textSize="20dp" />
<TextView
android:id="@+id/textView2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.00"
android:textColor="#f00"
android:textSize="20dp" />
</LinearLayout>
~~~
simple_item.xml,这是每个列表项的布局文件,左显示一张图片,右边是上下分布的两个文本框描述,这样就更加复杂了ListView的列表项
~~~
<?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,,作为列表项的一部分,id与java代码中相同-->
<ImageView
android:id="@+id/header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/tiger" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical" >
<!--定义一个TextView,,作为列表项的一部分-->
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:textColor="#f0f"
android:textSize="18dp" />
<!--定义一个TextView,,作为列表项的一部分-->
<TextView
android:id="@+id/desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:textSize="14dp" />
</LinearLayout>
</LinearLayout>
~~~
MainActivity.java
~~~
public class MainActivity extends Activity {
private String[] names=new String[]{
"虎头","弄玉","李清照","李白"
};
private String[] descs=new String[]{
"可爱的老虎","一个擅长音乐的女孩","一个擅长文学的女性","浪漫主义诗人"
};
private int[] imagesIds=new int[]{
R.drawable.tiger,R.drawable.nongyu,R.drawable.qingzhao,R.drawable.libai
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView show=(TextView) findViewById(R.id.textView1);
final TextView show2=(TextView) findViewById(R.id.textView2);
//创建一个List集合。List集合的元素是Map
List<Map<String,Object>> listItems=new ArrayList<Map<String,Object>>();
//第一步:创建List集合
//for循环,为list赋值
for(int i=0;i<names.length;i++){
Map<String,Object> item=new HashMap<String,Object>();
item.put("header", imagesIds[i]);
item.put("personName", names[i]);
item.put("desc", descs[i]);
//把列表项放入到list中
listItems.add(item);
}
//第二步:设置SimpleAdapter的参数
/*SimpleAdapter对象,需要5个参数,后面4个是关键
* 第2个参数:是一个List<Map<? extends Map<string,?>>的集合对象,集合中的每个 Map<string,?>对象是一个列表项
* 第3个参数:该参数指定一个列表项布局界面的ID
* 第4个参数:一个String[]类型的参数,决定提取Map对象中的那些key值对应的value类生成类表项
* 就是:需要显示值
* 第5个参数:int[]类型的参数,决定填充哪些 组件,就是使用显示值得组件Id
* 注意:第4,5个参数的数组需要一一对应才行
*/
SimpleAdapter sd=new SimpleAdapter(this,listItems,R.layout.simple_item,new String[]{"personName","header","desc"},new int[]{R.id.name,R.id.header,R.id.desc});
//为ListView设置Adapter
ListView list=(ListView) findViewById(R.id.listView1);
list.setAdapter(sd);//第三步,添加adapter
//为列表项设置单击事件
list.setOnItemClickListener(new OnItemClickListener(){
//第position项被单击时触发该方法
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
show.setText(names[position]+"是"+descs[position]);
}
});
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9aba8b24.jpg)
当需要监听用户单击,选中某个列表项时间,可以通过adapterview的
setOnItemClickListener方法
~~~
//为列表项设置单击事件
listview.setOnItemClickListener(new OnItemClickListener(){
//第position项被单击时触发该方法
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
//添加操作
}
});
~~~
**使用SimpleAdapter分三步:**
1,创建List<Map<String,Object>>集合
2,设置SimpleAdapter参数
3,为ListView添加simpleadpater
四,扩展BaseAdapter创建ListView
**扩展BaseAdapter:**
(1)创建类,继承自BaseAdapter
(2)重写其中的四个方法
①int getCount():返回的是数据源对象的个数,即列表项数
②Object getItem(int position):返回指定位置position上的列表
③long getItemId(int position):返回指定位置处的行ID
④View getView():返回列表项对应的视图,方法体中
◆实例化视图填充器
◆用视图填充器,根据Xml文件,实例化视图
◆根据布局找到控件,并设置属性
◆返回View视图
main.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="vertical">
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
~~~
MainActivity.java
~~~
package com.hust.baseadaptertest;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
ListView mylistview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mylistview=(ListView)findViewById(R.id.listView1);
//自定义baseadapter:程序要创建多少个列表项,每个列表项的组件都有开发者来决定
BaseAdapter ba=new BaseAdapter(){
//自动重写这4个函数
@Override
public int getCount() {
// TODO Auto-generated method stub
return 20;//指定一共包含20个选项
}
//返回值决定第position处的列表项内容
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
//重写该方法,该方法的返回值将作为列表项的ID
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
//重写该方法,该方法返回的View将作为列表框,决定第position处的列表项组件对象
/*
* Get a View that displays the data at the specified position in the data set.
* You can either create a View manually or inflate it from an XML layout file.
* When the View is inflated, the parent View (GridView, ListView...) will apply default layout parameters
* unless you use android.view.LayoutInflater.inflate(int, android.view.ViewGroup, boolean)
* to specify a root view and to prevent attachment to the root.
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
/*
* 手动创建列表项的布局文件
* */
//创建以个LinearLayout,并向其中添加两个组件
LinearLayout line=new LinearLayout(MainActivity.this);
line.setOrientation(0);
//一个ImageView组件
ImageView image=new ImageView(MainActivity.this);
image.setImageResource(R.drawable.ic_launcher);
//一个TextView组件
TextView text=new TextView(MainActivity.this);
text.setText("第"+(position+1)+"个列表项");
text.setTextSize(20);
text.setTextColor(Color.RED);
//两个组件添加到布局组件中
line.addView(image);
line.addView(text);
//返回布局组件
return line;
}
};
//设置adapter
mylistview.setAdapter(ba);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9abc9f72.jpg)
总结一下:
1:声明AdapterView对象子类(ListView,Spinner,Gallary,GridView),根据ID利用findViewById方法找到此对象
2:声明Adapter对象,根据构造方法实例化此对象。具体如下:
(1)ArrayAdapter<数据类型> adapter = new ArrayAdapter<数据类型>(context:一般指当前Activity对象,layout:每个列表项显示的布局,data:数据源变量);
(2)SimpleAdapter adapter = new SimpleAdapter(context:一般指当前Activity对象,data:数据源变量,layout:每个列表项显示的布局,new String[]{}:数据源中的“键”,new int[]{}:显示数据源的控件ID);
(3)自定义Adapter类 adapter = new 自定义Adapter类构造方法;
3:绑定Adapter对象到Adapter上
AdapterView对象.setAdapter(Adapter对象);