Android——Adapter
-
基本概念
Adapter(适配器),将一个类的接口变换成客户端所期待的一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。显然Adapter的存在就是为了配合两个不同部分之间的互相协作,使之能够协调工作。在Android中,Adapter是前台UI与底层数据之间联系的纽带,它们之间的关系可表示如下图。
-
常用Adapter
Adapter本身只是一个接口,它派生了ListAdapter和SpinnerAdapter两个子接口,其中ListAdapter为AbsListView提供列表项,而SpinnerAdapter为AbsSpinner提供列表项。Adapter接口及其实现类的继承关系如下图所示。
其中,BaseAdapter、ArrayAdapter、SimpleAdapter、SimpleCursorAdapter这几个是比较常用的Adapter。从上图中可以,看出BaseAdapter是比较重要的,在整个继承关系中处于比较关键的位置。Adapter常用的实现类简介如下:
ArrayAdapter<T>
任意类型(T)数组适配器
BaseAdapter
实现了公共基类Adapter,因此适用于ListView(通过实现指定的ListAdapter接口)和Spinner(通过实现指定的SpinnerAdapter接口)
CursorAdapter
将Cursor中的数据暴露给ListView控件
HeaderViewListAdapter
适用于有ListView Header的ListView控件
ListAdapter
扩展了Adapter,是ListViewts_列表数据之间的桥梁
ResourceCursorAdapter
创建在XML文件中定义的views
SimpleAdapter
将静态数据映射到XML文件定义的view中,功能非常强大
SimpleCursorAdapter
将cursor中的列映射到XML文件定义的TextView或ImageView中
SpinnerAdapter
扩展了Adapter,是Spinnerts_数据之间的桥梁
WrapperListAdapter
包含另外一个列表Adapter的列表Adapter
- 使用举例
这是基本的方法,直接在XML界面中创建ListView,然后在对应的Activity类中进行Adapter绑定即可。注意,AdapterDemo继承自Activity
效果如下:
Java文件如下所示:
package com.example.adapterdemo; import android.app.Activity; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.ListView; public class AdapterDemo extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_adapterdemo); String[] data= {"北京","上海","广州","西安","南京","深圳","杭州"}; ListView myLV = (ListView)findViewById(R.id.myListView); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.mylv_item,data); myLV.setAdapter(adapter); } }
Item布局如下,为一个简单的TextView,用于定制每个Item的布局:
<?xml version="1.0" encoding="utf-8"?> <TextView android:id="@+id/mylv_item" android:textSize="18sp" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:android="http://schemas.android.com/apk/res/android"> </TextView>
主界面布局如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <ListView android:id="@+id/myListView" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout>
这个方式继承的是ListActivity类,而不是Activity类。ListActivity类默认显示一个列表来展示数据,而且提供Item被点击时的可进行相关操作的方法。
ListActivity的子类无须调用setContentView()方法来显示某个界面,而是可以直接传入一个内容Adapter,ListActivity的子类就可以呈现出一个列表。
ListActivity持有一个ListView对象,ListActivity无须界面布局文件——相当于它的布局文件中只有一个ListView,因此只要为ListActivity设置Adapter即可。当然用户可以自己定制一个布局,然后在onCreate()方法中通过setContentView(int layoutId)方法来设置用户的自定义布局。需要指出的是,由开发者指定界面布局文件中应该包含一个id为"@+id/android:list"(如果使用代码形式,则是android.R.id.lsit)的ListView。
效果如下:
Java类文件如下,此例不需要布局文件,即Xml文件里可以什么没有,或者直接不需要XML布局文件。直接一个java文件就可以了。
package com.example.listactivitydemo; import android.app.ListActivity; import android.os.Bundle; import android.widget.ArrayAdapter; public class ListActivityDemo extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_ts_list); //不需要布局文件,如果需要定制布局文件,则需要按上述说明,按规定指定@+id/android:list,上述详见说明 String [] str = {"HeFie","BeiJing"}; ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.support_simple_spinner_dropdown_item,str); setListAdapter(adapter); } }
SimpleAdapter的功能不简单,相反它具有非常强大的功能,利用它,我们可以定制ListView的外观,或者更复杂的ListView列表项,ListView的大部分场景都可以使用SimpleAdapter。
效果如下:
Java类文件
package com.example.simpleadapter_demo; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.ListView; import android.widget.SimpleAdapter; public class SimpleAdapter_Demo extends Activity { private String[] nameStrings = new String[]{"小红","小明","小华"}; private String[] descsStrings = new String[]{"红红","明明","华华",}; private int[] imageIds = new int[]{R.drawable.libai,R.drawable.nongyu,R.drawable.qingzhao,R.drawable.tiger}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_simple_adapter__demo); List<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>(); for(int i=0; i<nameStrings.length; i++) { Map<String, Object> listItem = new HashMap<String, Object>(); listItem.put("header", imageIds[i]); listItem.put("personName", nameStrings[i]); listItem.put("decs", descsStrings[i]); listItems.add(listItem); } SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems, R.layout.simple_item, new String[] {"personName","header","decs"}, new int[]{R.id.name,R.id.header,R.id.desc}); ListView mylistview = (ListView)findViewById(R.id.mylistview); mylistview.setAdapter(simpleAdapter); } }
XML列表项布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <!-- 定义一个ImageView,用于作为列表项的一部分。 --> <ImageView android:id="@+id/header" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="10dp" /> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <!-- 定义一个TextView,用于作为列表项的一部分。 --> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20dp" android:textColor="#f0f" android:paddingLeft="10dp" /> <!-- 定义一个TextView,用于作为列表项的一部分。 --> <TextView android:id="@+id/desc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="14dp" android:paddingLeft="10dp" /> </LinearLayout> </LinearLayout>
XML主界面布局只有一个ListView:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <ListView android:id="@+id/mylistview" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </RelativeLayout>
使用BaseAdapter可以取得对Adapter最大的控制权,程序要创建多少列表项,每个列表项的组件都由开发者来决定。
效果如下:
Java类文件:
package com.example.baseadapter; import java.util.List; 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 BaseAdapter_Demo extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_base_adapter__demo); ListView myList = (ListView) findViewById(R.id.myList); BaseAdapter adapter = new BaseAdapter() { @Override public int getCount() { // 指定一共包含40个选项 return 40; } @Override public Object getItem(int position) { return null; } // 重写该方法,该方法的返回值将作为列表项的ID @Override public long getItemId(int position) { return position; } // 重写该方法,该方法返回的View将作为列表框 @Override public View getView(int position , View convertView , ViewGroup parent) { // 创建一个LinearLayout,并向其中添加2个组件 LinearLayout line = new LinearLayout(BaseAdapter_Demo.this); line.setOrientation(0); ImageView image = new ImageView(BaseAdapter_Demo.this); image.setImageResource(R.drawable.ic_launcher); TextView text = new TextView(BaseAdapter_Demo.this); text.setText("第" + (position +1 ) + "个列表项"); text.setTextSize(20); text.setTextColor(Color.RED); line.addView(image); line.addView(text); // 返回LinearLayout实例 return line; } }; myList.setAdapter(adapter); } }
XML布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+id/myList" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>