java list适配器_详解listview的四种适配器模式
ListView是Android開發(fā)中比較常用的一個(gè)組件,它以列表的形式展示具體內(nèi)容,并且能夠根據(jù)數(shù)據(jù)的長度自適應(yīng)顯示。比如說我們手機(jī)里的通訊錄就使用到了ListView顯示聯(lián)系人信息。ListView同時(shí)也是所有Android UI控件中最為麻煩的控件,之所以麻煩就是因?yàn)樗母鞣N的適配器特別麻煩。
創(chuàng)建ListView有兩種方式:
1、直接創(chuàng)建ListView
2、讓Activity繼承ListActivity
列表的顯示需要三個(gè)元素:
1.ListVeiw :用來展示列表的View。
2.適配器 :用來把數(shù)據(jù)映射到ListView上的中介。
3.數(shù)據(jù)集 ? :具體的將被映射的字符串,圖片,或者基本組件。
根據(jù)列表的適配器類型,列表分為四種,ArrayAdapter、SimpleAdapter、SimpleCursorAdapter以及自定義Adapter。
其中以ArrayAdapter最為簡(jiǎn)單,只能展示一行字。SimpleAdapter有最好的擴(kuò)充性,可以自定義出各種效果。 SimpleCursorAdapter可以認(rèn)為是SimpleAdapter對(duì)數(shù)據(jù)庫的簡(jiǎn)單結(jié)合,可以方面的把數(shù)據(jù)庫的內(nèi)容以列表的形式展示出來。
下面我們就通過幾個(gè)簡(jiǎn)單的例子講解一下通過各種適配器來構(gòu)建ListView。
1、1使用ArrayAdatpter構(gòu)建ListView
新建一個(gè)Android項(xiàng)目:ListViewDemo,同時(shí)新建一個(gè)類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 {
//定義一個(gè)ListView
private ListView mListView;
//定義一個(gè)String數(shù)組,數(shù)組里的數(shù)據(jù)就是ListView里的一項(xiàng)
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一個(gè)ListView
mListView = new ListView(this);
//通過setAdapter構(gòu)建一個(gè)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ù)就需要一個(gè)連接ListView視圖對(duì)象和數(shù)組數(shù)據(jù)的適配器來兩者的適配工作,ArrayAdapter的構(gòu)造需要三個(gè)參數(shù),依次為this,布局文件(注意這里的布局文件描述的是列表的每一行的布局,android.R.layout.simple_list_item_1是系統(tǒng)定義好的布局文件只顯示一行文字,數(shù)據(jù)源(一個(gè)List集合)。同時(shí)用setAdapter()完成適配的最后工作。運(yùn)行后的現(xiàn)實(shí)結(jié)構(gòu)如下圖:
1、2使用SimpleAdapter構(gòu)建ListView
使用simpleAdapter的數(shù)據(jù)用一般都是HashMap構(gòu)成的List,list的每一節(jié)對(duì)應(yīng)ListView的每一行。HashMap的每個(gè)鍵值數(shù)據(jù)映射到布局文件中對(duì)應(yīng)id的組件上。下面我們使用SimpleAdapter模擬一個(gè)通訊錄。
因?yàn)橄到y(tǒng)沒有對(duì)應(yīng)的布局文件可用,我們可以自己定義一個(gè)布局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"/>
新建一個(gè)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)","揚(yáng)偉","范劍"};
private String[] info_Phones={"13844445144","13844444444","13444445144","13544445144","13644445144","13744445144"};
private String[] info_Regions={"火星","水星","木星","月球","美國","未知地區(qū)"};
//定義一個(gè)ArrayList數(shù)組,每一條數(shù)據(jù)對(duì)應(yīng)通訊錄中的一個(gè)聯(lián)系人信息
private ArrayList> mInfos= new ArrayList>();
//定義一個(gè)ListView
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//new一個(gè)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);
}
//定義一個(gè)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});
//設(shè)置mListView的適配器為adapter
mListView.setAdapter(adapter);
setContentView(mListView);
}
}
使用simpleAdapter的數(shù)據(jù)用一般都是HashMap構(gòu)成的List,list的每一節(jié)對(duì)應(yīng)ListView的每一行。HashMap的每個(gè)鍵 值數(shù)據(jù)映射到布局文件中對(duì)應(yīng)id的組件上。因?yàn)橄到y(tǒng)沒有對(duì)應(yīng)的布局文件可用,我們可以自己定義一個(gè)布局info.xml。運(yùn)行效果如下圖:
我相信肯定有人對(duì)new SimpleAdapter()中的參數(shù)有一些疑問,下面我們就來看一下SimpleAdapter的構(gòu)造函數(shù):SimpleAdapter(Context context, List extends Map > data, int resource, String[] from, int[] to) ,context相信不用解釋了,假設(shè)將SimpleAdapter用于ListView。那么ListView的每一個(gè)列表項(xiàng)就是resource參數(shù)值指定的布局。而data參數(shù)就是要加載到ListView中的數(shù)據(jù)。那么from和to呢?在加載列表項(xiàng)時(shí),需要通過組件的id和data參數(shù)中List元素中的Map對(duì)象對(duì)應(yīng)。因此,from參數(shù)為Map對(duì)象的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對(duì)象中key為”img”的value綁定到R.id.info_img,將Map對(duì)象中key為”name”的value綁定到R.id.info_name,phone、region也類似。所以from和to中的參數(shù)是一一對(duì)應(yīng)的關(guān)系。同時(shí)?from又是對(duì)應(yīng)的Map中的key,to又是對(duì)應(yīng)布局文件中相應(yīng)組件的ID。
1、3使用SimpleCursorAdapter?構(gòu)建ListView
相比SimpleAdapter,SimpleCursorAdapter?就是方便把從游標(biāo)得到的數(shù)據(jù)進(jìn)行列表顯示,并可以把指定的列映射到對(duì)應(yīng)的組件中。SimpleCursorAdapter的構(gòu)造函數(shù)與SimpleAdapter的區(qū)別就是多了一個(gè)Cursor?c:SimpleCursorAdapter(Context?context, int layout,?Cursor?c,?String[]?from, int[] to),Cursor就是游標(biāo),如果你不清楚游標(biāo)的概念,就想像成數(shù)據(jù)查詢后的一個(gè)結(jié)果集。下面是一個(gè)通過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)通訊錄時(shí),需要如下權(quán)限:
左圖上是系統(tǒng)通訊錄中的聯(lián)系人,右圖是運(yùn)行的結(jié)果。
1、4使用自定義Adapter構(gòu)建ListView
當(dāng)我們使用系統(tǒng)自帶的ArrayAdapter、SimpleAdapter和SimpleCursorAdapter適配器時(shí),對(duì)于事件的響應(yīng)只能局限在一個(gè)行單位。假設(shè)一行里面有一個(gè)按鈕和一個(gè)圖片控件,它們之間的響應(yīng)操作是不一樣的。若采用系統(tǒng)自帶的適配器,就不能精確到每個(gè)控件的響應(yīng)事件。這時(shí),我們一般采取自定義適配器來實(shí)現(xiàn)這個(gè)比較精確地請(qǐng)求。我們?cè)傩陆ㄒ粋€(gè)MyAdapterListActivity繼承Activity,使用自定義適配器來實(shí)現(xiàn)SimpleAdapterListView中的效果,并新增一個(gè)多選框和按鈕。效果如下:
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)","揚(yáng)偉","范劍"};
private String[] info_Phones={"13844445144","13844444444","13444445144","13544445144","13644445144","13744445144"};
private String[] info_Regions={"火星","水星","木星","月球","美國","未知"};
//定義一個(gè)ArrayList數(shù)組,每一條數(shù)據(jù)對(duì)應(yīng)通訊錄中的一個(gè)聯(lián)系人信息
private ArrayList> mInfos= new ArrayList>();
//定義一個(gè)ListView
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//new一個(gè)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; //運(yùn)行上下文
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)建視圖容器并設(shè)置上下文
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);
//獲取控件對(duì)象
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);
//設(shè)置控件集到convertView
convertView.setTag(listItemView);
//設(shè)置聯(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);
}
});
// 注冊(cè)多選框狀態(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;
}
/**
* 記錄勾選了哪個(gè)聯(lián)系人
* @param checkedID 選中的聯(lián)系人序號(hào)
*/
private void checkedChange(int checkedID) {
hasChecked[checkedID] = !hasChecked(checkedID);
}
/**
* 判斷聯(lián)系人是否選擇
* @param checkedID 聯(lián)系人序號(hào)
* @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")+"詳細(xì)信息")
.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構(gòu)建ListView
如果程序的窗口僅僅需要顯示一個(gè)列表,則可以讓Activity直接繼續(xù)ListActivity來實(shí)現(xiàn)。ListActivity的子類無需調(diào)用setContentView()方法來顯示某個(gè)界面,而是可以直接傳入一個(gè)Adapter,ListActivity的子類就可以呈現(xiàn)出一個(gè)列表。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ū)"};
//定義一個(gè)ArrayList數(shù)組,每一條數(shù)據(jù)對(duì)應(yīng)通訊錄中的一個(gè)聯(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);
}
//定義一個(gè)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});
//本例中沒有聲明一個(gè)ListView,但通過繼承ListActivity使用setListAdapter然后傳入一個(gè)適配器即可直接顯示一個(gè)列表。
setListAdapter(adapter);
}
}
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的java list适配器_详解listview的四种适配器模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 厨房油渍怎么清洗
- 下一篇: oracle pi 3.14,Oracl