您好,登錄后才能下訂單哦!
本文主要給大家介紹ListView 的多選操作模式,文章內(nèi)容都是筆者用心摘選和編輯的,具有一定的針對(duì)性,對(duì)大家的參考意義還是比較大的,下面跟筆者一起了解下ListView 的多選操作模式吧。
<LinearLayout 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" android:orientation="vertical" > <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:onClick="showSelectAuthors" android:text="@string/select_authors" android:textSize="25sp" /> <ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:choiceMode="multipleChoice" /> </LinearLayout>
Activity的代碼如下,沒有用適配器來處理數(shù)據(jù),簡(jiǎn)單使用了ArrayAdapter:
package com.example.choicelistviewtest2; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; public class RadioButtonListActivity extends Activity { private ListView radioButtonList; private String[] names = new String[] { "芥川龍之介", "三島由紀(jì)夫", "川端康成", "村上春樹", "東野圭吾", "張愛玲", "金庸", "錢鐘書", "老舍", "梁實(shí)秋", "亨利米勒", "海明威", "菲茲杰拉德", "凱魯亞克", "杰克倫敦", "小仲馬", "杜拉斯", "福樓拜", "雨果", "巴爾扎克", "莎士比亞", "勞倫斯", "毛姆", "柯南道爾", "笛福" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); radioButtonList = (ListView) findViewById(R.id.list); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, names); radioButtonList.setAdapter(adapter); } public void showSelectAuthors(View v) { long[] authorsId = radioButtonList.getCheckItemIds(); String name = ""; String message; if (authorsId.length > 0) { // 用戶至少選擇了一位作家 for (int i = 0; i < authorsId.length; i++) { name += "," + names[(int) authorsId[i]]; } // 將第一個(gè)作家前面的“,”去掉 message = name.substring(1); } else { message = "請(qǐng)至少選擇一位作家!"; } Toast.makeText(RadioButtonListActivity.this, message, Toast.LENGTH_LONG) .show(); } }
上面的代碼是成功的,程序運(yùn)行也OK,本以為可以這樣結(jié)束了,卻發(fā)現(xiàn)一個(gè)問題:
從圖上可以看出“getCheckItemIds()”這個(gè)方法是棄用的。事實(shí)上ListView的getCheckItemIds()方法所得到數(shù)據(jù)并不精確,據(jù)說在某些Android版本上測(cè)試發(fā)現(xiàn),當(dāng)我們選中ListView的一條Item,然后再次取消,getCheckItemIds()方法還是可以拿到取消的Item的id,即返回的數(shù)組中還保留該id。這是源碼自己的Bug。
雖然經(jīng)過測(cè)試,我的手機(jī)上沒發(fā)現(xiàn)這個(gè)問題(我的手機(jī)Android版本是4.3),但是我想這個(gè)方法還是避免使用吧。版本更新后Android推薦使用的是“getCheckedItemIds()”這個(gè)方法(注意方法名多加了“ed”),不過這個(gè)方法也不是那么好用——“Returns the set of checked items ids. The result is only valid if the choice mode has not been set to CHOICE_MODE_NONE and the adapter has stable IDs. (hasStableIds() == true)?!边@個(gè)方法返回ListView中被選中Item的id集合。該方法使用有兩個(gè)條件,第一是ListView的選擇模式?jīng)]有被設(shè)置為CHOICE_MODE_NONE(這一點(diǎn)我們滿足,我們?cè)O(shè)置ListView的選擇模式為CHOICE_MODE_MULTIPLE),第二是適配器有穩(wěn)定的 ID(hasStableIds()==true)。這一點(diǎn)是不滿足的,諸如ArrayAdapter、SimpleAdapter,不支持穩(wěn)定的ID(可以通過adapter.hasStableIds()方法查看,返回值為false)。這就要求我們自己創(chuàng)建Adapter,從 hasStableIds()方法中返回true。
我只好又自定義適配器試了一下這個(gè)方法,是成功的,布局文件沒有改變,就不再貼了,主要是適配器,代碼如下:
package com.example.choicelistviewtest3; import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; public class RadioAdapter extends BaseAdapter { private String[] authors; private Context c; public RadioAdapter(Context c, String[] authors) { super(); this.c = c; this.authors = authors; } @Override public int getCount() { return authors.length; } @Override public Object getItem(int arg0) { return null; } @Override public long getItemId(int arg0) { //返回每一條Item的Id return arg0; } @Override public boolean hasStableIds() { //getCheckedItemIds()方法要求此處返回為真 return true; } @Override public View getView(int arg0, View arg1, ViewGroup arg2) { ChoiceListItemView choiceListItemView = new ChoiceListItemView(c, null); choiceListItemView.setName(authors[arg0]); return choiceListItemView; } }
ChoiceListItemView類與《ListView的單選模式》中的大同小異,只是去掉了Button背景的設(shè)置,還原CheckBox原有的樣子,因?yàn)楝F(xiàn)在ListView是多選模式。ChoiceListItemView代碼與它的XML文件(Item的布局文件)如下:
package com.example.choicelistviewtest3; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.CheckBox; import android.widget.Checkable; import android.widget.LinearLayout; import android.widget.TextView; public class ChoiceListItemView extends LinearLayout implements Checkable { private TextView nameTxt; private CheckBox selectBtn; public ChoiceListItemView(Context context, AttributeSet attrs) { super(context, attrs); LayoutInflater inflater = LayoutInflater.from(context); View v = inflater.inflate(R.layout.item_list, this, true); nameTxt = (TextView) v.findViewById(R.id.author); selectBtn = (CheckBox) v.findViewById(R.id.radio); } public void setName(String text) { nameTxt.setText(text); } @Override public boolean isChecked() { return selectBtn.isChecked(); } @Override public void setChecked(boolean checked) { selectBtn.setChecked(checked); } @Override public void toggle() { selectBtn.toggle(); } }
<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="wrap_content" android:background="#fff" android:orientation="horizontal" > <TextView android:id="@+id/author" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:padding="10dp" android:textSize="20sp" /> <CheckBox android:id="@+id/radio" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_gravity="center_vertical" android:clickable="false" android:focusable="false" android:focusableInTouchMode="false" android:padding="10dp" /> </RelativeLayout>
這樣,在主類中就可以使用“getCheckedItemIds()”這個(gè)方法了,代碼如下:
package com.example.choicelistviewtest3; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.ListView; import android.widget.Toast; public class RadioButtonListActivity extends Activity { private ListView radioButtonList; private RadioAdapter adapter; private String[] authors = new String[] { "芥川龍之介", "三島由紀(jì)夫", "川端康成", "村上春樹", "東野圭吾", "張愛玲", "金庸", "錢鐘書", "老舍", "梁實(shí)秋", "亨利米勒", "海明威", "菲茲杰拉德", "凱魯亞克", "杰克倫敦", "小仲馬", "杜拉斯", "福樓拜", "雨果", "巴爾扎克", "莎士比亞", "勞倫斯", "毛姆", "柯南道爾", "笛福" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_radio_button_list); radioButtonList = (ListView) findViewById(R.id.list); adapter = new RadioAdapter(this, authors); radioButtonList.setAdapter(adapter); } public void showSelectAuthors(View v) { long[] authorsId = radioButtonList.getCheckedItemIds(); String name = ""; String message; if (authorsId.length > 0) { // 用戶至少選擇了一位作家 for (int i = 0; i < authorsId.length; i++) { name += "," + authors[(int) authorsId[i]]; } // 將第一個(gè)作家前面的“,”去掉 message = name.substring(1); } else { message = "請(qǐng)至少選擇一位作家!"; } Toast.makeText(RadioButtonListActivity.this, message, Toast.LENGTH_LONG) .show(); } }
它與choicelistviewtest2包中的RadioButtonListActivity 相比(也就是剛開始的那個(gè)RadioButtonListActivity 類),變化很小。顯然,如果只是簡(jiǎn)單地顯示一下作家的名字和復(fù)選框,而并不需要太多的要求,自定義Adapter實(shí)現(xiàn)擁有穩(wěn)定的ID,這樣做事實(shí)上是比較麻煩的。下面換一種簡(jiǎn)單的方法,還是使用ArrayAdapter,只是需要自己來寫獲取選中Item的ID的方法了,將choicelistviewtest2包中的RadioButtonListActivity增加一個(gè)方法:
package com.example.choicelistviewtest2; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; public class RadioButtonListActivity extends Activity { private ListView radioButtonList; private String[] names = new String[] { "芥川龍之介", "三島由紀(jì)夫", "川端康成", "村上春樹", "東野圭吾", "張愛玲", "金庸", "錢鐘書", "老舍", "梁實(shí)秋", "亨利米勒", "海明威", "菲茲杰拉德", "凱魯亞克", "杰克倫敦", "小仲馬", "杜拉斯", "福樓拜", "雨果", "巴爾扎克", "莎士比亞", "勞倫斯", "毛姆", "柯南道爾", "笛福" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); radioButtonList = (ListView) findViewById(R.id.list); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, names); radioButtonList.setAdapter(adapter); } public void showSelectAuthors(View v) { // long[] authorsId = radioButtonList.getCheckItemIds(); long[] authorsId = getListSelectededItemIds(radioButtonList); String name = ""; String message; if (authorsId.length > 0) { // 用戶至少選擇了一位作家 for (int i = 0; i < authorsId.length; i++) { name += "," + names[(int) authorsId[i]]; } // 將第一個(gè)作家前面的“,”去掉 message = name.substring(1); } else { message = "請(qǐng)至少選擇一位作家!"; } Toast.makeText(RadioButtonListActivity.this, message, Toast.LENGTH_LONG) .show(); } // 避免使用getCheckItemIds()方法 public long[] getListSelectededItemIds(ListView listView) { long[] ids = new long[listView.getCount()];//getCount()即獲取到ListView所包含的item總個(gè)數(shù) //定義用戶選中Item的總個(gè)數(shù) int checkedTotal = 0; for (int i = 0; i < listView.getCount(); i++) { //如果這個(gè)Item是被選中的 if (listView.isItemChecked(i)) { ids[checkedTotal++] = i; } } if (checkedTotal < listView.getCount()) { //定義選中的Item的ID數(shù)組 final long[] selectedIds = new long[checkedTotal]; //數(shù)組復(fù)制 ids System.arraycopy(ids, 0, selectedIds, 0, checkedTotal); return selectedIds; } else { //用戶將所有的Item都選了 return ids; } } }
其中用到了System.arraycopy()這個(gè)方法,解釋如下:
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) src:源數(shù)組; srcPos:源數(shù)組要復(fù)制的起始位置; dest:目的數(shù)組; destPos:目的數(shù)組放置的起始位置; length:復(fù)制的長(zhǎng)度。
這就真正OK了,效果圖:
看完以上關(guān)于ListView 的多選操作模式,很多讀者朋友肯定多少有一定的了解,如需獲取更多的行業(yè)知識(shí)信息 ,可以持續(xù)關(guān)注我們的行業(yè)資訊欄目的。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。