Android从零单排之Adapter及其子类

时间:2022-08-31 22:44:05

    Adapter--适配器,相信大家在开发中少不了用这个类或者它的子类。本人也在很多地方都用到,所以在这里总结一下。

    Adapter扮演了一个桥梁的角色,把AdapterView和数据源板绑定一起。AdapterView是什么呢?它其实就是一个view,只不过是一种需要在代码中动态设置内容的view,而不是像其他的button,imageview等组件一样,可以在xml文件中指定属性和显示的数据。

    下面看一下Adapter和AdapterView的类图:

Android从零单排之Adapter及其子类

Android从零单排之Adapter及其子类

   我们一般使用的AdapterView的子类有:ListView、GridView、Gallery、Spinner等,使用最多的Adapter(适配器)有ArrayAdapter、SimpleAdapter、SimpleCursorAdapter、BaseAdapter等。

    使用adapter一般需要三步:

    1. 在布局文件中设置好你所使用的AdapterView的相关属性。

    2. 在代码中使用适配器(adapter及其子类)对AdapterView进行适配。此时就可以正常显示了。

    3. 添加监听器,对AdapterView的一些触发事件进行处理。

    下面我就这四个适配器进行详细的解释一下。


一、ArrayAdapter

   这是一种最简单的Adapter,通常将数组或list集合包装成多个列表项。我们就以ListView为例。

先看布局文件:

    <!--
android:divider="#f00" 设置分割线的颜色
android:dividerHeight="2dp" 设置分割线的高度
android:stackFromBottom="true" 设置列表显示的时候显示到最下面的列表
android:scrollbars="none" 隐藏滚动条
android:fadeScrollbars="false" 为false时滚动条一直显示,为true时自动显示隐藏
-->

<ListView
android:id="@+id/array_adapter_lv1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#1d953f"
android:divider="#f00"
android:listSelector="#E9967A"
android:dividerHeight="2dp"
android:headerDividersEnabled="false"
android:transcriptMode="alwaysScroll" >
</ListView>


java代码部分:

private void initListView1() {
listView1 = (ListView) findViewById(R.id.array_adapter_lv1);
String[] arr1 = new String[] { "item1", "item2", "item3" };
ArrayAdapter<String> adapter1 = new ArrayAdapter<>(this,
android.R.layout.simple_list_item_1, arr1);
listView1.setAdapter(adapter1);
}

    ArrayAdapter的构造函数有很多,我用的是三个参数的那个,下面来解释一下参数的含义。

  • Context:表示访问android应用的接口
  • textViewResourceId: 资源ID,代表了一个TextView,这个TextView作为ArrayAdapter的列表项组件。
  • 数组或者List:为多个列表项提供数据。

    其中,第二个参数比较重要,可以使用系统提供的布局文件,也可以自己定义(必须以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="wrap_content"
android:layout_height="wrap_content"
android:textSize="12pt"
android:textColor="#8DB6CD"
android:text="TextView" />

    然后在代码中,指定自己定义的xml文件就可以了。

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.array_adapter_item, getResources().getStringArray(R.array.array1));

    其实还可以自定义ArrayAdapter来实现复杂一点的布局。这种方式的重点就是重写ArrayAdapter的getView(int position, View convertView, ViewGroup parent)

    首先,定义你所需要的布局。

<?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="wrap_content"
android:orientation="horizontal" >
<ImageView
android:id="@+id/id_simple_adapter2_iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="@+id/id_simple_adapter2_tv1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="11" />
<TextView
android:id="@+id/id_simple_adapter2_tv2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="22" />
</LinearLayout>
</LinearLayout>


    其次,需要继承ArrayAdapter这个类,重写getView方法。

public class MyArrayAdapter extends ArrayAdapter<User> {

private int resourceId;

public MyArrayAdapter(Context context, int textViewResourceId,
List<User> objects) {
super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout linearLayout = null;
User user = getItem(position);
if (convertView == null) {
linearLayout = new LinearLayout(getContext());
LayoutInflater inflater = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(resourceId, linearLayout, true);
} else {
linearLayout = (LinearLayout) convertView;
}
ImageView iv = (ImageView) linearLayout
.findViewById(R.id.id_simple_adapter2_iv);
TextView tv1 = (TextView) linearLayout
.findViewById(R.id.id_simple_adapter2_tv1);
TextView tv2 = (TextView) linearLayout
.findViewById(R.id.id_simple_adapter2_tv2);
iv.setBackgroundResource(user.getImg());
tv1.setText(user.getName());
tv2.setText(user.getNickName());

return linearLayout;
}

}
    最后,绑定适配器。
...........

MyArrayAdapter adapter = new MyArrayAdapter(this, R.layout.item_array_adapter2, users);
listView1.setAdapter(adapter);

    详细代码,请下载demo。


二、SimpleAdapter

    这个是用的最多的适配器了。它可以将静态数据映射到XML文件中定义好的视图,可以指定有Map组成的List类型的数据,Map中每一行数据就是界面上显示的一个条目。如果设置了     ListView的大部分应用场景,都可以通过SimpleAdapter来适配。来看下面这个例子: 首先是布局文件,其中包括一个ListView和一个GridView
<?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:background="#E0EEE0"
android:orientation="vertical" >
<ListView
android:id="@+id/simple_adapter_lv"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
<!-- android:listSelector="#8DB6CD" 选中一个item时的底色 -->
<GridView
android:id="@+id/simple_adapter_gv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dip"
android:horizontalSpacing="10dip"
android:listSelector="#8DB6CD"
android:numColumns="5"
android:verticalSpacing="10dip" >
</GridView>
</LinearLayout>

    下面就是对这两个AdapterView进行适配了。SimpleAdapter需要5个参数:

android.widget.SimpleAdapter.SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)

  • Context:这个就不用多说了。
  • List<?extends Map<String, ?>>:该集合中每个Map<String, ?>对象生成一个列表项。
  • 第三个参数是一个界面布局的ID,需要指定适配的AdapterView所在的布局文件。
  • 第四个参数是一个String类型的数组,该参数决定了Map<String, ?>对象中哪些Key对应的value来生成列表项。
  • 第五个参数是int类型的数组,需要指定AdapterView控件的ID,就是指定把数据填充到哪些控件上。

private void initListView() {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map = new HashMap<>();
map.put("img", R.drawable.songjiang);
map.put("tv1", "人间恰似水泊");
map.put("tv2", "情义兰舟通彼岸");
list.add(map);
map = new HashMap<>();
map.put("img", R.drawable.wuyong);
map.put("tv1", "众兄弟兵器可利?");
map.put("tv2", "吹毛得过!");
list.add(map);
map = new HashMap<>();
map.put("img", R.drawable.gongsunsheng);
map.put("tv1", "众兄弟战袍可新?");
map.put("tv2", "焕然一新!");
list.add(map);
map = new HashMap<>();
map.put("img", R.drawable.luzhishen);
map.put("tv1", "众兄弟此战可胜?");
map.put("tv2", "战无不胜!");
list.add(map);

listView = (ListView) findViewById(R.id.simple_adapter_lv);
SimpleAdapter adapter = new SimpleAdapter(this, list,
R.layout.item_simple_adapter, new String[] { "img", "tv1",
"tv2" }, new int[] { R.id.simple_lv_img,
R.id.simple_lv_tv1, R.id.simple_lv_tv2 });
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
}

private void initGridView() {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map = new HashMap<>();
map.put("img", R.drawable.chaijin);
map.put("tv1", "柴进");
map.put("tv2", "小旋风");
list.add(map);
map = new HashMap<>();
map.put("img", R.drawable.huarong);
map.put("tv1", "花荣");
map.put("tv2", "小李广");
list.add(map);
//此处省略一部分代码......
map = new HashMap<>();
map.put("img", R.drawable.yanqing);
map.put("tv1", "燕青");
map.put("tv2", "浪子");
list.add(map);
map = new HashMap<>();
map.put("img", R.drawable.panjinlian);
map.put("tv1", "潘金莲");
map.put("tv2", "xxx");
list.add(map);

gridView = (GridView) findViewById(R.id.simple_adapter_gv);
SimpleAdapter adapter = new SimpleAdapter(this, list,
R.layout.item_simple_adapter2, new String[] { "img", "tv1",
"tv2" }, new int[] { R.id.simple_grid_lv_img,
R.id.simple_grid_lv_tv1, R.id.simple_grid_lv_tv2 });
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(this);
}

    接下来,添加可以添加监听事件了,具体怎么响应你的事件,就看你怎么写了!

@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
if (parent.getId() == R.id.simple_adapter_lv) {
Toast.makeText(getApplicationContext(), position + "",
Toast.LENGTH_SHORT).show();
} else if (parent.getId() == R.id.simple_adapter_gv) {
Toast.makeText(
getApplicationContext(),
((TextView) view.findViewById(R.id.simple_grid_lv_tv1))
.getText(), Toast.LENGTH_SHORT).show();
}
}



三、SimpleCursorAdapter

四、BaseAdapter