安卓ListView詳解

學(xué)習(xí)Android的同學(xué)注意了N床!B汀!

學(xué)習(xí)過程中遇到什么問題或者想獲取學(xué)習(xí)資源的話茎辐,歡迎加入Android學(xué)習(xí)交流群宪郊,群號碼:364595326? 我們一起學(xué)Android掂恕!

在android開發(fā)中ListView是比較常用的組件,它以列表的形式展示具體內(nèi)容弛槐,并且能夠根據(jù)數(shù)據(jù)的長度自適應(yīng)顯示懊亡。抽空把對ListView的使用做了整理,并寫了個小例子乎串,如下圖店枣。

列表的顯示需要三個元素:

1.ListVeiw 用來展示列表的View。

2.適配器?用來把數(shù)據(jù)映射到ListView上的中介叹誉。

3.?dāng)?shù)據(jù)????具體的將被映射的字符串鸯两,圖片,或者基本組件长豁。

根據(jù)列表的適配器類型钧唐,列表分為三種,ArrayAdapter匠襟,SimpleAdapter和SimpleCursorAdapter

其中以ArrayAdapter最為簡單钝侠,只能展示一行字。SimpleAdapter有最好的擴(kuò)充性酸舍,可以自定義出各種效果帅韧。SimpleCursorAdapter可以認(rèn)為是SimpleAdapter對數(shù)據(jù)庫的簡單結(jié)合,可以方面的把數(shù)據(jù)庫的內(nèi)容以列表的形式展示出來父腕。

我們從最簡單的ListView開始:

/**

* @author allin

*

*/

publicclassMyListViewextendsActivity {

privateListView listView;

//private List data = new ArrayList();

@Override

publicvoidonCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

listView =newListView(this);

listView.setAdapter(newArrayAdapter(this, android.R.layout.simple_expandable_list_item_1,getData()));

setContentView(listView);

}

privateList getData(){

List data =newArrayList();

data.add("測試數(shù)據(jù)1");

data.add("測試數(shù)據(jù)2");

data.add("測試數(shù)據(jù)3");

data.add("測試數(shù)據(jù)4");

returndata;

}

上面代碼使用了ArrayAdapter(Contextcontext, int textViewResourceId,List objects)來裝配數(shù)據(jù)弱匪,要裝配這些數(shù)據(jù)就需要一個連接ListView視圖對象和數(shù)組數(shù)據(jù)的適配器來兩者的適配工作,ArrayAdapter的構(gòu)造需要三個參數(shù)璧亮,依次為this,布局文件(注意這里的布局文件描述的是列表的每一行的布局萧诫,android.R.layout.simple_list_item_1是系統(tǒng)定義好的布局文件只顯示一行文字,數(shù)據(jù)源(一個List集合)枝嘶。同時用setAdapter()完成適配的最后工作帘饶。運行后的現(xiàn)實結(jié)構(gòu)如下圖:

SimpleCursorAdapter

sdk的解釋是這樣的:An easy adapter to map columns from a cursor to TextViews or

ImageViews defined in an XML file. You can specify which columns you want, which

views you want to display the columns, and the XML file that defines the

appearance of these views。簡單的說就是方便把從游標(biāo)得到的數(shù)據(jù)進(jìn)行列表顯示群扶,并可以把指定的列映射到對應(yīng)的TextView中及刻。

下面的程序是從電話簿中把聯(lián)系人顯示到類表中。先在通訊錄中添加一個聯(lián)系人作為數(shù)據(jù)庫的數(shù)據(jù)竞阐。然后獲得一個指向數(shù)據(jù)庫的Cursor并且定義一個布局文件(當(dāng)然也可以使用系統(tǒng)自帶的)缴饭。

/**

* @author allin

*

*/

publicclassMyListView2extendsActivity {

privateListView listView;

//private List data = new ArrayList();

@Override

publicvoidonCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

listView =newListView(this);

Cursor cursor = getContentResolver().query(People.CONTENT_URI,null,null,null,null);

startManagingCursor(cursor);

ListAdapter listAdapter =newSimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_1,

cursor,

newString[]{People.NAME},

newint[]{android.R.id.text1});

listView.setAdapter(listAdapter);

setContentView(listView);

}

Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);先獲得一個指向系統(tǒng)通訊錄數(shù)據(jù)庫的Cursor對象獲得數(shù)據(jù)來源。

startManagingCursor(cursor);我們將獲得的Cursor對象交由Activity管理骆莹,這樣Cursor的生命周期和Activity便能夠自動同步颗搂,省去自己手動管理Cursor。

SimpleCursorAdapter

構(gòu)造函數(shù)前面3個參數(shù)和ArrayAdapter是一樣的幕垦,最后兩個參數(shù):一個包含數(shù)據(jù)庫的列的String型數(shù)組丢氢,一個包含布局文件中對應(yīng)組件id的int型數(shù)組傅联。其作用是自動的將String型數(shù)組所表示的每一列數(shù)據(jù)映射到布局文件對應(yīng)id的組件上。上面的代碼疚察,將NAME列的數(shù)據(jù)一次映射到布局文件的id為text1的組件上蒸走。

注意:需要在AndroidManifest.xml中如權(quán)限:

android:name="android.permission.READ_CONTACTS">

運行后效果如下圖:

SimpleAdapter

simpleAdapter的擴(kuò)展性最好,可以定義各種各樣的布局出來貌嫡,可以放上ImageView(圖片)比驻,還可以放上Button(按鈕),CheckBox(復(fù)選框)等等衅枫。下面的代碼都直接繼承了ListActivity嫁艇,ListActivity和普通的Activity沒有太大的差別,不同就是對顯示ListView做了許多優(yōu)化弦撩,方面顯示而已。

下面的程序是實現(xiàn)一個帶有圖片的類表论皆。

首先需要定義好一個用來顯示每一個列內(nèi)容的xml

vlist.xml

android:orientation="horizontal" android:layout_width="fill_parent"

android:layout_height="fill_parent">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="5px"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:textColor="#FFFFFFFF"

android:textSize="22px" />

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:textColor="#FFFFFFFF"

android:textSize="13px" />

下面是實現(xiàn)代碼:

/**

* @author allin

*

*/

publicclassMyListView3extendsListActivity {

// private List data = new ArrayList();

@Override

publicvoidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

SimpleAdapter adapter =newSimpleAdapter(this,getData(),R.layout.vlist,

newString[]{"title","info","img"},

newint[]{R.id.title,R.id.info,R.id.img});

setListAdapter(adapter);

}

privateList> getData() {

List> list =newArrayList>();

Map map =newHashMap();

map.put("title","G1");

map.put("info","google 1");

map.put("img", R.drawable.i1);

list.add(map);

map =newHashMap();

map.put("title","G2");

map.put("info","google 2");

map.put("img", R.drawable.i2);

list.add(map);

map =newHashMap();

map.put("title","G3");

map.put("info","google 3");

map.put("img", R.drawable.i3);

list.add(map);

returnlist;

}

使用simpleAdapter的數(shù)據(jù)用一般都是HashMap構(gòu)成的List益楼,list的每一節(jié)對應(yīng)ListView的每一行。HashMap的每個鍵值數(shù)據(jù)映射到布局文件中對應(yīng)id的組件上点晴。因為系統(tǒng)沒有對應(yīng)的布局文件可用感凤,我們可以自己定義一個布局vlist.xml。下面做適配粒督,new一個SimpleAdapter參數(shù)一次是:this陪竿,布局文件(vlist.xml),HashMap的

title 和 info屠橄,img族跛。布局文件的組件id,title锐墙,info礁哄,img。布局文件的各組件分別映射到HashMap的各元素上溪北,完成適配桐绒。

運行效果如下圖:

有按鈕的ListView

但是有時候,列表不光會用來做顯示用之拨,我們同樣可以在在上面添加按鈕茉继。添加按鈕首先要寫一個有按鈕的xml文件,然后自然會想到用上面的方法定義一個適配器蚀乔,然后將數(shù)據(jù)映射到布局文件上烁竭。但是事實并非這樣,因為按鈕是無法映射的乙墙,即使你成功的用布局文件顯示出了按鈕也無法添加按鈕的響應(yīng)颖变,這時就要研究一下ListView是如何現(xiàn)實的了生均,而且必須要重寫一個類繼承BaseAdapter。下面的示例將顯示一個按鈕和一個圖片腥刹,兩行字如果單擊按鈕將刪除此按鈕的所在行马胧。并告訴你ListView究竟是如何工作的。效果如下:

vlist2.xml

android:orientation="horizontal"

android:layout_width="fill_parent"

android:layout_height="fill_parent">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="5px"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:textColor="#FFFFFFFF"

android:textSize="22px" />

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:textColor="#FFFFFFFF"

android:textSize="13px" />

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/s_view_btn"

android:layout_gravity="bottom|right" />

程序代碼:

/**

* @author allin

*

*/

publicclassMyListView4extendsListActivity {

privateList> mData;

@Override

publicvoidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

mData = getData();

MyAdapter adapter =newMyAdapter(this);

setListAdapter(adapter);

}

privateList> getData() {

List> list =newArrayList>();

Map map =newHashMap();

map.put("title","G1");

map.put("info","google 1");

map.put("img", R.drawable.i1);

list.add(map);

map =newHashMap();

map.put("title","G2");

map.put("info","google 2");

map.put("img", R.drawable.i2);

list.add(map);

map =newHashMap();

map.put("title","G3");

map.put("info","google 3");

map.put("img", R.drawable.i3);

list.add(map);

returnlist;

}

// ListView 中某項被選中后的邏輯

@Override

protectedvoidonListItemClick(ListView l, View v,intposition,longid) {

Log.v("MyListView4-click", (String)mData.get(position).get("title"));

}

/**

* listview中點擊按鍵彈出對話框

*/

publicvoidshowInfo(){

newAlertDialog.Builder(this)

.setTitle("我的listview")

.setMessage("介紹...")

.setPositiveButton("確定",newDialogInterface.OnClickListener() {

@Override

publicvoidonClick(DialogInterface dialog,intwhich) {

}

})

.show();

}

publicfinalclassViewHolder{

publicImageView img;

publicTextView title;

publicTextView info;

publicButton viewBtn;

}

publicclassMyAdapterextendsBaseAdapter{

privateLayoutInflater mInflater;

publicMyAdapter(Context context){

this.mInflater = LayoutInflater.from(context);

}

@Override

publicintgetCount() {

// TODO Auto-generated method stub

returnmData.size();

}

@Override

publicObject getItem(intarg0) {

// TODO Auto-generated method stub

returnnull;

}

@Override

publiclonggetItemId(intarg0) {

// TODO Auto-generated method stub

return0;

@Override

publicView getView(intposition, View convertView, ViewGroup parent) {

ViewHolder holder =null;

if(convertView ==null) {

holder=newViewHolder();

convertView = mInflater.inflate(R.layout.vlist2,null);

holder.img = (ImageView)convertView.findViewById(R.id.img);

holder.title = (TextView)convertView.findViewById(R.id.title);

holder.info = (TextView)convertView.findViewById(R.id.info);

holder.viewBtn = (Button)convertView.findViewById(R.id.view_btn);

convertView.setTag(holder);

}else{

holder = (ViewHolder)convertView.getTag();

}

holder.img.setBackgroundResource((Integer)mData.get(position).get("img"));

holder.title.setText((String)mData.get(position).get("title"));

holder.info.setText((String)mData.get(position).get("info"));

holder.viewBtn.setOnClickListener(newView.OnClickListener() {

@Override

publicvoidonClick(View v) {

showInfo();

}

});

returnconvertView;

}


下面將對上述代碼衔峰,做詳細(xì)的解釋佩脊,listView在開始繪制的時候,系統(tǒng)首先調(diào)用getCount()函數(shù)垫卤,根據(jù)他的返回值得到listView的長度(這也是為什么在開始的第一張圖特別的標(biāo)出列表長度)威彰,然后根據(jù)這個長度,調(diào)用getView()逐一繪制每一行穴肘。如果你的getCount()返回值是0的話歇盼,列表將不顯示同樣return

1,就只顯示一行评抚。

系統(tǒng)顯示列表時豹缀,首先實例化一個適配器(這里將實例化自定義的適配器)。當(dāng)手動完成適配時慨代,必須手動映射數(shù)據(jù)邢笙,這需要重寫getView()方法。系統(tǒng)在繪制列表的每一行的時候?qū)⒄{(diào)用此方法侍匙。getView()有三個參數(shù)氮惯,position表示將顯示的是第幾行,covertView是從布局文件中inflate來的布局想暗。我們用LayoutInflater的方法將定義好的vlist2.xml文件提取成View實例用來顯示妇汗。然后將xml文件中的各個組件實例化(簡單的findViewById()方法)。這樣便可以將數(shù)據(jù)對應(yīng)到各個組件上了江滨。但是按鈕為了響應(yīng)點擊事件铛纬,需要為它添加點擊監(jiān)聽器,這樣就能捕獲點擊事件唬滑。至此一個自定義的listView就完成了告唆,現(xiàn)在讓我們回過頭從新審視這個過程。系統(tǒng)要繪制ListView了晶密,他首先獲得要繪制的這個列表的長度擒悬,然后開始繪制第一行,怎么繪制呢稻艰?調(diào)用getView()函數(shù)懂牧。在這個函數(shù)里面首先獲得一個View(實際上是一個ViewGroup),然后再實例并設(shè)置各個組件,顯示之僧凤。好了畜侦,繪制完這一行了。那再繪制下一行躯保,直到繪完為止旋膳。在實際的運行過程中會發(fā)現(xiàn)listView的每一行沒有焦點了,這是因為Button搶奪了listView的焦點途事,只要布局文件中將Button設(shè)置為沒有焦點就OK了验懊。

運行效果如下圖:


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市尸变,隨后出現(xiàn)的幾起案子义图,更是在濱河造成了極大的恐慌,老刑警劉巖召烂,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碱工,死亡現(xiàn)場離奇詭異涎嚼,居然都是意外死亡涩笤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門粹淋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來桶蛔,“玉大人,你說我怎么就攤上這事漫谷∽欣祝” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵舔示,是天一觀的道長碟婆。 經(jīng)常有香客問我,道長惕稻,這世上最難降的妖魔是什么竖共? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮俺祠,結(jié)果婚禮上公给,老公的妹妹穿的比我還像新娘。我一直安慰自己蜘渣,他們只是感情好淌铐,可當(dāng)我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蔫缸,像睡著了一般腿准。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拾碌,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天吐葱,我揣著相機(jī)與錄音街望,去河邊找鬼。 笑死弟跑,一個胖子當(dāng)著我的面吹牛灾前,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播窖认,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼豫柬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了扑浸?” 一聲冷哼從身側(cè)響起烧给,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎喝噪,沒想到半個月后础嫡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡酝惧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年榴鼎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晚唇。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡巫财,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出哩陕,到底是詐尸還是另有隱情平项,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布悍及,位于F島的核電站闽瓢,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏心赶。R本人自食惡果不足惜扣讼,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缨叫。 院中可真熱鬧椭符,春花似錦、人聲如沸弯汰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咏闪。三九已至曙搬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纵装。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工征讲, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人橡娄。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓诗箍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親挽唉。 傳聞我的和親對象是個殘疾皇子滤祖,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容