1 AdapterView类简介
1.1 AdapterView组件是一组重要的组件,AdapterView本身是一个抽线类,实际使用更多的都是Adapter相关子类,AdapterView具有如下特征:
- AdapterView继承了ViewGroup,它的本质是容器
- AdapterView可以包括多个列表项,并将多个“列表项”以合适的形式显示出来
- AdapterView显示的多个列表项有Adapter提供,调用AdapterView的setAdapter(Adapter)方法设置Adapter即可
1.2 AdapterView及其子类的继承关系视图
2 ListView和ListActivity
2.1 创建ListView的两种方式:
- 直接使用ListView进行创建
- 让Activity继承ListActivity(相当于该Activity显示的ListView)
2.2 ListView、GridView、Spinner、Gallery等AdapterView都只是容器,而Adapter负责提供每个“列表项”组件,AdapterView则负责采用合适的方式显示这些列表项
3 Adapter接口及实现
3.1 Adapter接口来由
Adapter是连接后端数据和前端显示的适配器接口,是数据和UI(View)之间一个重要的纽带。在常见的View(ListView,GridView)等地方都需要用到Adapter。如下图直观的表达了Data、Adapter、View三者的关系:
3.2 Adapter类视图
由图可以看到在Android中与Adapter有关的所有接口、类的完整层级图。在我们使用过程中可以根据自己的需求实现接口或者继承类进行一定的扩展。比较常用的有 BaseAdapter,SimpleAdapter,ArrayAdapter,SimpleCursorAdapter等。
- BaseAdapter是一个抽象类,继承它需要实现较多的方法,所以也就具有较高的灵活性;
- ArrayAdapter支持泛型操作,最为简单,只能展示一行字。
- SimpleAdapter有最好的扩充性,可以自定义出各种效果。
- SimpleCursorAdapter可以适用于简单的纯文字型ListView,它需要Cursor的字段和UI的id对应起来。如需要实现更复杂的UI也可以重写其他方法。可以认为是SimpleAdapter对数据库的简单结合,可以方便地把数据库的内容以列表的形式展示出来。
3.3 实现Adapter的方式
- 使用ArrayAdapter,列表的显示需要三个元素:
- ListVeiw 用来展示列表的View。
- 适配器 用来把数据映射到ListView上的中介。
- 数据 具体的将被映射的字符串,图片,或者基本组件。
- 使用SimpleAdapter
- 可以定义各种各样的布局出来,可以放上ImageView(图片),还可以放上Button(按钮),CheckBox(复选框)等等。但只能是TextView视图及其子视图
-
是一个简单的适配器,可以将静态数据映射到XML文件中定义好的视图。该数据用一般都是HashMap构建List,list的每一节对应ListView的每一行,根据Map中的数据映射关键字到指定的视图。
-
绑定数据到视图分两个阶段,首先,如果设置了SimpleAdapter.ViewBinder,那么setViewValue(android.view.View, Object, String)将被重写。如果setViewValue的返回值是true,则表示绑定已经完成,将不再调用系统默认的绑定实现。如果返回值为false,视图将按以下顺序绑定数据: (如果View实现了Checkable(例如CheckBox),期望绑定值是一个布尔类型。)----> (TextView.期望绑定值是一个字符串类型,通过调用setViewText(TextView, String)绑定。)----> (ImageView,期望绑定值是一个资源id或者一个字符串,通过调用setViewImage(ImageView, int) 或 setViewImage(ImageView, String)绑定数据。)
- ListItem中子视图的事件响应也是在SimpleAdapter.ViewBinder的setViewValue方法中完成的
- HashMap的每个键值数据映射到布局文件中对应id的组件上。系统没有对应的布局文件可用,需要自定义一个布局vlist.xml。
- new一个SimpleAdapter参数一次是:Context / List<? extends Map<String, ?>> / @LayoutRes int resource / String[] from / @IdRes int[] to
-
BaseAdapter
- 有时候,列表不光会用来做显示用,我们同样可以在在上面添加按钮。添加按钮首先要写一个有按钮的xml文件,然后自然会想到用上面的方法定义一个适配器,然后将数据映射到布局文件上。但是事实并非这样,因为按钮是无法映射的,即使你成功的用布局文件显示出了按钮也无法添加按钮的响应,这时就要研究一下ListView是如何现实的了,而且必须要重写一个类继承BaseAdapter。下面的示例将显示一个按钮和一个图片,两行字如果单击按钮将删除此按钮的所在行。并告诉你ListView究竟是如何工作的。
3.4 示例:使用SimpleAdapter来实现ListView
activity文件
import android.app.Activity; import android.app.ListActivity; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; public class ListActivityTest extends Activity { private String[] names = {"孙悟空", "猪八戒", "牛魔王", "沙和尚"}; private String[] descs = {"厉害的猴子", "不戒的猪", "丑陋的牛", "忠诚的和尚"}; private int[] imageIds = {R.drawable.monkey, R.drawable.pig, R.drawable.bull, R.drawable.monk}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.list_activity_main); List<Map<String, Object>> listItems = new ArrayList<>(); for (int i = 0; i < names.length; i++) { Map<String, Object> listItem = new HashMap<>(); listItem.put("header", imageIds[i]); listItem.put("name", names[i]); listItem.put("desc", descs[i]); //listItem. listItems.add(listItem); } SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems, R.layout.simple_item, new String[]{"header", "name", "desc"}, new int[]{R.id.header, R.id.name, R.id.desc}); ListView listView = (ListView) findViewById(R.id.myList); listView.setAdapter(simpleAdapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(ListActivityTest.this, names[position] + "被单机了", Toast.LENGTH_SHORT).show(); } }); } }