java list适配器_详解listview的四种适配器模式
ListView是Android開發(fā)中比較常用的一個組件,它以列表的形式展示具體內(nèi)容,并且能夠根據(jù)數(shù)據(jù)的長度自適應顯示。比如說我們手機里的通訊錄就使用到了ListView顯示聯(lián)系人信息。ListView同時也是所有Android UI控件中最為麻煩的控件,之所以麻煩就是因為它的各種的適配器特別麻煩。
創(chuàng)建ListView有兩種方式:
1、直接創(chuàng)建ListView
2、讓Activity繼承ListActivity
列表的顯示需要三個元素:
1.ListVeiw :用來展示列表的View。
2.適配器 :用來把數(shù)據(jù)映射到ListView上的中介。
3.數(shù)據(jù)集 ? :具體的將被映射的字符串,圖片,或者基本組件。
根據(jù)列表的適配器類型,列表分為四種,ArrayAdapter、SimpleAdapter、SimpleCursorAdapter以及自定義Adapter。
其中以ArrayAdapter最為簡單,只能展示一行字。SimpleAdapter有最好的擴充性,可以自定義出各種效果。 SimpleCursorAdapter可以認為是SimpleAdapter對數(shù)據(jù)庫的簡單結合,可以方面的把數(shù)據(jù)庫的內(nèi)容以列表的形式展示出來。
下面我們就通過幾個簡單的例子講解一下通過各種適配器來構建ListView。
1、1使用ArrayAdatpter構建ListView
新建一個Android項目:ListViewDemo,同時新建一個類ListViewDemoActivity繼承Activity,代碼如下:package com.liuzhichao.listview;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class ListViewDemoActivity extends Activity {
//定義一個ListView
private ListView mListView;
//定義一個String數(shù)組,數(shù)組里的數(shù)據(jù)就是ListView里的一項
private String[] items={"1、ArrayAdapter_List","2、SimpleAdapter_List"
,"3、SimpleCursorAdapter_List","4、MyAdapter_List"};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//new一個ListView
mListView = new ListView(this);
//通過setAdapter構建一個ArrayAdapter將items與mListView"綁定"
mListView.setAdapter(new ArrayAdapter(this,
android.R.layout.simple_list_item_1, items));
//顯示mListView
setContentView(mListView);
}
}
上面代碼使用了ArrayAdapter(Context context, int textViewResourceId, List objects)來裝配數(shù)據(jù),要裝配這些數(shù)據(jù)就需要一個連接ListView視圖對象和數(shù)組數(shù)據(jù)的適配器來兩者的適配工作,ArrayAdapter的構造需要三個參數(shù),依次為this,布局文件(注意這里的布局文件描述的是列表的每一行的布局,android.R.layout.simple_list_item_1是系統(tǒng)定義好的布局文件只顯示一行文字,數(shù)據(jù)源(一個List集合)。同時用setAdapter()完成適配的最后工作。運行后的現(xiàn)實結構如下圖:
1、2使用SimpleAdapter構建ListView
使用simpleAdapter的數(shù)據(jù)用一般都是HashMap構成的List,list的每一節(jié)對應ListView的每一行。HashMap的每個鍵值數(shù)據(jù)映射到布局文件中對應id的組件上。下面我們使用SimpleAdapter模擬一個通訊錄。
因為系統(tǒng)沒有對應的布局文件可用,我們可以自己定義一個布局info.xml:<?xml version="1.0" encoding="utf-8"?>
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
android:id="@+id/info_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:src="@drawable/ic_launcher"/>
android:id="@+id/info_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/info_img"
android:layout_marginTop="5dp"/>
android:id="@+id/info_phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/info_name"
android:layout_toRightOf="@id/info_img"
android:layout_alignBaseline="@id/info_img"/>
android:id="@+id/info_region"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/info_phone"
android:layout_alignBaseline="@id/info_phone"
android:layout_marginLeft="10dip"/>
新建一個SimpleAdapterListView繼續(xù)Activity,代碼如下:package com.liuzhichao.listview;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;
public class SimpleAdapterListView extends Activity{
//分別定義通訊錄中的用戶名、電話、地區(qū)等信息
private String[] info_Names={"史珍香","賴月京","秦壽生","劉產(chǎn)","揚偉","范劍"};
private String[] info_Phones={"13844445144","13844444444","13444445144","13544445144","13644445144","13744445144"};
private String[] info_Regions={"火星","水星","木星","月球","美國","未知地區(qū)"};
//定義一個ArrayList數(shù)組,每一條數(shù)據(jù)對應通訊錄中的一個聯(lián)系人信息
private ArrayList> mInfos= new ArrayList>();
//定義一個ListView
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//new一個ListView
mListView = new ListView(this);
//添加聯(lián)系人信息
for(int i=0;i
Map item = new HashMap();
item.put("img", R.drawable.contact_img);
item.put("name", info_Names[i]);
item.put("phone", info_Phones[i]);
item.put("region", info_Regions[i]);
mInfos.add(item);
}
//定義一個SimpleAdapter
SimpleAdapter adapter = new SimpleAdapter(this, mInfos, R.layout.info,
new String[]{"img","name","phone","region"},
new int[]{R.id.info_img,R.id.info_name,R.id.info_phone,R.id.info_region});
//設置mListView的適配器為adapter
mListView.setAdapter(adapter);
setContentView(mListView);
}
}
使用simpleAdapter的數(shù)據(jù)用一般都是HashMap構成的List,list的每一節(jié)對應ListView的每一行。HashMap的每個鍵 值數(shù)據(jù)映射到布局文件中對應id的組件上。因為系統(tǒng)沒有對應的布局文件可用,我們可以自己定義一個布局info.xml。運行效果如下圖:
我相信肯定有人對new SimpleAdapter()中的參數(shù)有一些疑問,下面我們就來看一下SimpleAdapter的構造函數(shù):SimpleAdapter(Context context, List extends Map > data, int resource, String[] from, int[] to) ,context相信不用解釋了,假設將SimpleAdapter用于ListView。那么ListView的每一個列表項就是resource參數(shù)值指定的布局。而data參數(shù)就是要加載到ListView中的數(shù)據(jù)。那么from和to呢?在加載列表項時,需要通過組件的id和data參數(shù)中List元素中的Map對象對應。因此,from參數(shù)為Map對象的key,而to表示組件的id,例如,本例中的參數(shù)值為from=new String[]{“img”,”name”,”phone”,”region”},to=new int[]{R.id.info_img,R.id.info_name,R.id.info_phone,R.id.info_region}),意思就是將Map對象中key為”img”的value綁定到R.id.info_img,將Map對象中key為”name”的value綁定到R.id.info_name,phone、region也類似。所以from和to中的參數(shù)是一一對應的關系。同時?from又是對應的Map中的key,to又是對應布局文件中相應組件的ID。
1、3使用SimpleCursorAdapter?構建ListView
相比SimpleAdapter,SimpleCursorAdapter?就是方便把從游標得到的數(shù)據(jù)進行列表顯示,并可以把指定的列映射到對應的組件中。SimpleCursorAdapter的構造函數(shù)與SimpleAdapter的區(qū)別就是多了一個Cursor?c:SimpleCursorAdapter(Context?context, int layout,?Cursor?c,?String[]?from, int[] to),Cursor就是游標,如果你不清楚游標的概念,就想像成數(shù)據(jù)查詢后的一個結果集。下面是一個通過SimpleCursorAdapter 使用ListView顯示系統(tǒng)通訊錄中聯(lián)系人的例子。package com.liuzhichao.listview;
import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract.Contacts;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
public class SimpleCursorAdapterActivity extends Activity {
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
mListView = new ListView(this);
Cursor cursor=this.getContentResolver().query(Contacts.CONTENT_URI, null, null, null, null);
SimpleCursorAdapter adapter=new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_2, cursor,
new String[]{Contacts.DISPLAY_NAME},
new int[]{android.R.id.text1});
mListView.setAdapter(adapter);
setContentView(mListView);
}
}
注意:在讀取系統(tǒng)通訊錄時,需要如下權限:
左圖上是系統(tǒng)通訊錄中的聯(lián)系人,右圖是運行的結果。
1、4使用自定義Adapter構建ListView
當我們使用系統(tǒng)自帶的ArrayAdapter、SimpleAdapter和SimpleCursorAdapter適配器時,對于事件的響應只能局限在一個行單位。假設一行里面有一個按鈕和一個圖片控件,它們之間的響應操作是不一樣的。若采用系統(tǒng)自帶的適配器,就不能精確到每個控件的響應事件。這時,我們一般采取自定義適配器來實現(xiàn)這個比較精確地請求。我們再新建一個MyAdapterListActivity繼承Activity,使用自定義適配器來實現(xiàn)SimpleAdapterListView中的效果,并新增一個多選框和按鈕。效果如下:
MyAdapterListActivity.java:package com.liuzhichao.listview;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class MyAdapterListActivity extends Activity {
//分別定義通訊錄中的用戶名、電話、地區(qū)等信息
private String[] info_Names={"史珍香","賴月京","秦壽生","劉產(chǎn)","揚偉","范劍"};
private String[] info_Phones={"13844445144","13844444444","13444445144","13544445144","13644445144","13744445144"};
private String[] info_Regions={"火星","水星","木星","月球","美國","未知"};
//定義一個ArrayList數(shù)組,每一條數(shù)據(jù)對應通訊錄中的一個聯(lián)系人信息
private ArrayList> mInfos= new ArrayList>();
//定義一個ListView
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//new一個ListView
mListView = new ListView(this);
//添加聯(lián)系人信息
for(int i=0;i
Map item = new HashMap();
item.put("img", R.drawable.contact_img);
item.put("name", info_Names[i]);
item.put("phone", info_Phones[i]);
item.put("region", info_Regions[i]);
mInfos.add(item);
}
MyAdapter adapter = new MyAdapter(this, mInfos);
mListView.setAdapter(adapter);
setContentView(mListView);
}
private class MyAdapter extends BaseAdapter {
private Context context; //運行上下文
private List> listItems; //聯(lián)系人信息集合
private LayoutInflater listContainer; //視圖容器
private boolean[] hasChecked; //記錄聯(lián)系人選中狀態(tài)
public final class ListItemView{ //自定義控件集合
public ImageView img;
public TextView name;
public TextView phone;
public TextView region;
public CheckBox check;
public Button detail;
}
public MyAdapter(Context context, List> listItems) {
this.context = context;
listContainer = LayoutInflater.from(context); //創(chuàng)建視圖容器并設置上下文
this.listItems = listItems;
hasChecked = new boolean[getCount()];
}
public int getCount() {
return listItems.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
final int selectID = position;
ListItemView listItemView = null;
if (convertView == null) {
listItemView = new ListItemView();
//獲取list_item布局文件的視圖
convertView = listContainer.inflate(R.layout.myinfo, null);
//獲取控件對象
listItemView.img = (ImageView)convertView.findViewById(R.id.info_img);
listItemView.name = (TextView)convertView.findViewById(R.id.info_name);
listItemView.phone = (TextView)convertView.findViewById(R.id.info_phone);
listItemView.region = (TextView)convertView.findViewById(R.id.info_region);
listItemView.detail= (Button)convertView.findViewById(R.id.btn);
listItemView.check = (CheckBox)convertView.findViewById(R.id.checkBox);
//設置控件集到convertView
convertView.setTag(listItemView);
//設置聯(lián)系人信息
listItemView.img.setBackgroundResource((Integer) listItems.get(
position).get("img"));
listItemView.name.setText((String) listItems.get(
position).get("name"));
listItemView.phone.setText((String) listItems.get(
position).get("phone"));
listItemView.region.setText((String) listItems.get(
position).get("region"));
//More按鈕事件
listItemView.detail.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
showDetailInfo(selectID);
}
});
// 注冊多選框狀態(tài)事件處理
listItemView.check
.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
//記錄聯(lián)系人選中狀態(tài)
checkedChange(selectID);
}
});
}else {
listItemView = (ListItemView)convertView.getTag();
}
return convertView;
}
/**
* 記錄勾選了哪個聯(lián)系人
* @param checkedID 選中的聯(lián)系人序號
*/
private void checkedChange(int checkedID) {
hasChecked[checkedID] = !hasChecked(checkedID);
}
/**
* 判斷聯(lián)系人是否選擇
* @param checkedID 聯(lián)系人序號
* @return 返回是否選中狀態(tài)
*/
public boolean hasChecked(int checkedID) {
return hasChecked[checkedID];
}
/**
* 顯示物品詳情
* @param clickID
*/
private void showDetailInfo(int clickID) {
new AlertDialog.Builder(context)
.setIcon(Integer.parseInt(listItems.get(clickID).get("img").toString()))
.setTitle(listItems.get(clickID).get("name")+"詳細信息")
.setMessage("電話:"+listItems.get(clickID).get("phone").toString()+" 地區(qū):"+listItems.get(clickID).get("region").toString())
.setPositiveButton("確定", null)
.show();
}
}
}
myinfo.xml:<?xml version="1.0" encoding="utf-8"?>
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
android:id="@+id/info_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"/>
android:id="@+id/info_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/info_img"
android:layout_marginTop="5dp"/>
android:id="@+id/info_phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/info_name"
android:layout_toRightOf="@id/info_img"
android:layout_alignBaseline="@id/info_img"/>
android:id="@+id/info_region"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/info_phone"
android:layout_alignBaseline="@id/info_phone"
android:layout_marginLeft="10dip"/>
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_alignBaseline="@id/info_img"
android:layout_toRightOf="@id/info_region"/>
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/checkBox"
android:layout_toRightOf="@id/checkBox"
android:text="More..."
/>
2、讓Activity繼承ListActivity構建ListView
如果程序的窗口僅僅需要顯示一個列表,則可以讓Activity直接繼續(xù)ListActivity來實現(xiàn)。ListActivity的子類無需調(diào)用setContentView()方法來顯示某個界面,而是可以直接傳入一個Adapter,ListActivity的子類就可以呈現(xiàn)出一個列表。package com.liuzhichao.listview;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import android.app.ListActivity;
import android.os.Bundle;
import android.widget.SimpleAdapter;
public class ListActivityList extends ListActivity {
//分別定義通訊錄中的用戶名、電話、地區(qū)等信息
private String[] info_Names={"***","***","***","***","***","***"};
private String[] info_Phones={"13844445144","13844444444","13444445144","13544445144","13644445144","13744445144"};
private String[] info_Regions={"火星","水星","木星","月球","美國","未知地區(qū)"};
//定義一個ArrayList數(shù)組,每一條數(shù)據(jù)對應通訊錄中的一個聯(lián)系人信息
private ArrayList> mInfos= new ArrayList>();
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//添加聯(lián)系人信息
for(int i=0;i
Map item = new HashMap();
item.put("img", R.drawable.contact_img);
item.put("name", info_Names[i]);
item.put("phone", info_Phones[i]);
item.put("region", info_Regions[i]);
mInfos.add(item);
}
//定義一個SimpleAdapter
SimpleAdapter adapter = new SimpleAdapter(this, mInfos, R.layout.info,
new String[]{"img","name","phone","region"},
new int[]{R.id.info_img,R.id.info_name,R.id.info_phone,R.id.info_region});
//本例中沒有聲明一個ListView,但通過繼承ListActivity使用setListAdapter然后傳入一個適配器即可直接顯示一個列表。
setListAdapter(adapter);
}
}
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的java list适配器_详解listview的四种适配器模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 厨房油渍怎么清洗
- 下一篇: 冒菜有肉香的味道怎么回事