轉載:http://www.lai18.com/content/1631131.html
這里的listview篩選是指listview的adapter實現filter來過濾數據。
“動態刪除"是指,使用filter篩選數據后,對篩選后的數據的刪除操作,實際上是對篩選前的數據產生影響。
實現目標:舉例來說:
Listview原來顯示:1,2,3,4,5,6,11,12,13,14
使用filter篩選“1”后顯示:1,11,12,13,14
此時我選中11(第二項),刪除之。當前應該還顯示1,12,13,14;而關閉篩選后,數據應該顯示:1,2,3,4,5,6,12,13,14
listview+adapter的使用方法見:
繼承BaseAdapter實現Filterable的adapter類完整示例
其中繼承BaseAdapter中getItemId(int position)方法介紹見:
Baseadapter的 getItem 和 getItemId 的作用和重寫
該方法通常是直接返回 position。但這在列表會變化時,如上述的篩選,是不正確的。
如果適配器中的數據有可以唯一標識數據的整型字段,可以將其返回,這在特定的幾個情況會用到。
如下:我在該函數返回了數據集_data中數據的getID()。
- @Override
- public long getItemId(int position) {
- // 自定義ID
- // 在此最好返回數據的唯一標識,在一些特定情況下使用到
- // 如果沒有,此處一般返回position
- return _data.get(position).getID();
- }
那么,會在什么時候用到適配器的getItemId方法呢?
上面的文章no.2說了,這個方法並不是給適配器使用的方法,實際上是用來在我們設置
setOnItemClickListener、setOnItemLongClickListener、setOnItemSelectedListener的點擊選擇處理事件中方便地調用來獲取當前行數據的。
來看下面的例子:長按listview事件,注意onItemClick的4個參數
- lvContent.setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view,
- int position, long id) {
- String s = String.format(
- "position+1:%s\nid:%s\ngetItemIdAtPosition:%s\n",
- position + 1, id,
- parent.getItemIdAtPosition(position));
- String s1 = "ViewTagVo:"
- + ((VoStation) view.getTag(R.id.tagVO)).getName();
- String s2 = "ParentItemVo:"
- + ((VoStation) parent.getItemAtPosition(position))
- .getName();
- Toast.makeText(getActivity(),
- s + "\n" + s1 + "\n" + s2 + "\n", Toast.LENGTH_LONG)
- .show();
- }
- });
上述代碼輸出的點擊列表中一項item時,該item的以下屬性:
position+1:來自參數,+1是為了方便比較
id:來自參數(我按順序給我的數據從1001開始賦值ID:1001,1002...)
getItemIdAtPosition:使用parent.getItemIdAtPosition(position)獲得的值。
我還比較了parent.getItemAtPosition(position) 和view.getTag獲得數據的一致性。
通常情況下,我們使用position來桉順序訪問列表,以及數據集,如_data.get(position),甚至使用position來刪除對應的項,這在列表固定時是可以正常使用的,如下:
(點擊 基站5)
但是。listview配合adpater實現filter接口,達到數據篩選的目的時,當前列表是會動態變化的,這時再點擊 基站5,如下:
可以看到,position屬性是指示item在當前適配器(包括filter后)的位置,這也是其本意。如果此時使用position屬性來刪除數據,刪除的實際上是position=0的“基站1”,而不是點擊的基站5.
所以,當需要對列表中項目進行操作時,最好給他配上唯一的ID,這個ID可以是臨時配給數據的,只要在當前adapter中可以唯一指定一個數據就行。
正確的刪除操作:(其中itemId是獲得到的id參數)
- for (int i = 0; i < datas.size(); i++) {
- if (datas.get(i).getID() == itemId) {
- datas.remove(i);
- adapter.resetData(datas);// 重設適配器的數據集
- if (TextUtils.isEmpty(_searchingWord))
- adapter.notifyDataSetChanged();// 通知修改數據
- else
- adapter.getFilter().filter(_searchingWord);
- }
- }
resetData() getFilter()方法,見開頭第一篇文章中的類定義。這里說一下思路:
1、遍歷數據集找到指定的ID (不使用position)
2、從數據集中移除該項,然后重置適配器的數據
3、通知數據變化(此處我用了一個判斷,_searchingWord是用戶當前正在搜索的關鍵字,如果為空,說明用戶在沒有篩選數據時刪除一項,可以直接通知數據變化來刷新listview。如果搜索關鍵字不為空,說明用戶是在搜索出某些項目時對其中的一項進行刪除。所以,刪除數據后我們再次對新的數據進行相同的過濾。否則直接顯示除了刪除項的其他數據,影響用戶體驗)。
最終效果如下:
(篩選出標題含5的基站:)
對基站5 進行刪除操作(我使用的長按彈出刪除菜單后刪除)
此時可以看到,基站5被刪除了,但是界面仍然顯示出了被篩選出的剩余的基站15。
此時關閉搜索框,如下:(基站5的確是被刪除了。)
剛開始學安卓,也不知道我實現這效果的方式對不對。歡迎指正。
