Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android使用ListView和CheckBox進行批量操作示例

Android使用ListView和CheckBox進行批量操作示例

編輯:Android開發實例

在使用ListView時,一般為了性能的提升,都會使用ViewHolder,也就是Item的View實現復用。

現在的問題是,當在ListView的Item中包含CheckBox,並且CheckBox的事件處理監聽器是holder.checkbox.setOnCheckedChangeListener()時,會出現第一項開始未選中,當第二項選中時第一項也跟著選中,這顯然不是我們想要的結果。

出現這個問題的原因是第一項和第二項用的是同一個Item,當第二項選中時,CheckBox的當前狀態為選中,這時setOnCheckedChangeListener裡面會改變第一項關聯的實體對象的屬性(引用類型,變量A、B都引用同一個對象AA,當A把AA的某個屬性值修改了,B再次訪問時,AA對象的那個屬性的值為A引用改後的值),代碼如下:

  1. holder.checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {  
  2.  
  3.             @Override 
  4.             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {  
  5.                 driver.setSelected(isChecked);  
  6.             }  
  7.  
  8.         });  

解決辦法:

1、在ListViewAdapter初始化時,將對象中有關CheckBox是否選中的屬性存儲起來。

  1. selectedMap = new HashMap<Integer, Boolean>();   
  2.       int size = mPersons.size();  
  3.       for (int i = 0; i < size; i++) {   
  4.           selectedMap.put(i, mPersons.get(i).isSelected());   
  5.       }  

2、去掉CheckBox的holder.checkbox.setOnCheckedChangeListener(){}事件監聽器

3、在Adapter裡的 public View getView(final int position, View convertView, ViewGroup parent){}方法體裡面,當前的CheckBox是否選中狀態,由之前初始化時保存的對象屬性值控制,代碼如下:

  1. boolean selected = selectedMap.get(position);  
  2. holder.checkbox.setChecked(selected);  

3、用戶點擊ListView的Item時,改變CheckBox的狀態,代碼如下:

  1. convertView.setOnClickListener(new View.OnClickListener() {  
  2.  
  3.            @Override 
  4.            public void onClick(View v) {  
  5.                checkbox.toggle();  
  6.                selectedMap.put(position, checkbox.isChecked());   
  7.                driver.setSelected(checkbox.isChecked());  
  8.            }  
  9.        });  

數據適配器ListViewAdapter的完整代碼:

  1. package com.easipass.cloud.ccp.adapter;  
  2.  
  3. import java.util.ArrayList;  
  4. import java.util.HashMap;  
  5.  
  6. import android.content.Context;  
  7. import android.view.LayoutInflater;  
  8. import android.view.View;  
  9. import android.view.ViewGroup;  
  10. import android.widget.BaseAdapter;  
  11. import android.widget.CheckBox;  
  12. import android.widget.Filter;  
  13. import android.widget.Filterable;  
  14. import android.widget.ImageView;  
  15. import android.widget.TextView;  
  16.  
  17. import com.easipass.R;  
  18. import com.easipass.cloud.ccp.entity.UserInfo;  
  19.  
  20. /**  
  21.  * 用戶列表數據適配器  
  22.  *   
  23.  * @author android_ls  
  24.  */ 
  25. public final class UserListViewAdapter extends BaseAdapter implements Filterable {  
  26.     private LayoutInflater inflater;  
  27.  
  28.     private MyFilter myFilter;  
  29.  
  30.     private final Object mLock = new Object();  
  31.  
  32.     private ArrayList<UserInfo> mPersons;  
  33.  
  34.     private ArrayList<UserInfo> mCheckValues;  
  35.  
  36.     public HashMap<Integer, Boolean> selectedMap;  
  37.  
  38.     public UserListViewAdapter(Context context, ArrayList<UserInfo> cms) {  
  39.         inflater = LayoutInflater.from(context);  
  40.         mPersons = cms;  
  41.  
  42.         selectedMap = new HashMap<Integer, Boolean>();  
  43.         int size = mPersons.size();  
  44.         for (int i = 0; i < size; i++) {  
  45.             selectedMap.put(i, mPersons.get(i).isSelected());  
  46.         }  
  47.  
  48.     }  
  49.  
  50.     @Override 
  51.     public int getCount() {  
  52.         return mPersons.size();  
  53.     }  
  54.  
  55.     @Override 
  56.     public Object getItem(int arg0) {  
  57.         return mPersons.get(arg0);  
  58.     }  
  59.  
  60.     @Override 
  61.     public long getItemId(int position) {  
  62.         return position;  
  63.     }  
  64.  
  65.     @Override 
  66.     public View getView(final int position, View convertView, ViewGroup parent) {  
  67.         ViewHolder holder = null;  
  68.         if (convertView == null) {  
  69.             convertView = inflater.inflate(R.layout.ccp_carmanager_lv_item, null);  
  70.             holder = new ViewHolder();  
  71.             holder.text1 = (TextView) convertView.findViewById(R.id.tv_name);  
  72.             holder.text2 = (TextView) convertView.findViewById(R.id.tv_phnoe);  
  73.             holder.checkbox = (CheckBox) convertView.findViewById(R.id.checkbox);  
  74.             holder.imageView = (ImageView) convertView.findViewById(R.id.iv_icon);  
  75.  
  76.             convertView.setTag(holder);  
  77.         } else {  
  78.             holder = (ViewHolder) convertView.getTag();  
  79.         }  
  80.  
  81.         final UserInfo driver = mPersons.get(position);  
  82.  
  83.         holder.text1.setText(driver.getName());  
  84.  
  85.         holder.text2.setText(driver.getPhoneNumber());  
  86.         // TODO 測試  
  87.         holder.imageView.setBackgroundResource(Integer.valueOf(driver.getIconUrl()));  
  88.         holder.checkbox.setVisibility(View.VISIBLE);  
  89.  
  90.         boolean selected = selectedMap.get(position);  
  91.         holder.checkbox.setChecked(selected);  
  92.  
  93.         final CheckBox checkbox = holder.checkbox;  
  94.         convertView.setOnClickListener(new View.OnClickListener() {  
  95.  
  96.             @Override 
  97.             public void onClick(View v) {  
  98.                 checkbox.toggle();  
  99.                 selectedMap.put(position, checkbox.isChecked());  
  100.                 driver.setSelected(checkbox.isChecked());  
  101.             }  
  102.         });  
  103.  
  104.         if (selected) {  
  105.             convertView.setClickable(false);  
  106.         }  
  107.  
  108.         return convertView;  
  109.     }  
  110.  
  111.     @Override 
  112.     public Filter getFilter() {  
  113.         if (myFilter == null) {  
  114.             myFilter = new MyFilter();  
  115.         }  
  116.         return myFilter;  
  117.     }  
  118.  
  119.     class MyFilter extends Filter {  
  120.  
  121.         @Override 
  122.         protected FilterResults performFiltering(CharSequence prefix) {  
  123.             FilterResults results = new FilterResults();  
  124.             if (mCheckValues == null) {  
  125.                 synchronized (mLock) {  
  126.                     mCheckValues = new ArrayList<UserInfo>(mPersons);  
  127.                 }  
  128.             }  
  129.  
  130.             if (prefix == null || prefix.length() == 0) {  
  131.                 synchronized (mLock) {  
  132.                     ArrayList<UserInfo> list = new ArrayList<UserInfo>(mCheckValues);  
  133.                     results.values = list;  
  134.                     results.count = list.size();  
  135.                 }  
  136.             } else {  
  137.                 String prefixString = prefix.toString().toLowerCase();  
  138.                 final ArrayList<UserInfo> values = mCheckValues;  
  139.                 final int count = values.size();  
  140.  
  141.                 final ArrayList<UserInfo> newValues = new ArrayList<UserInfo>(count);  
  142.                 for (int i = 0; i < count; i++) {  
  143.                     final UserInfo value = (UserInfo) values.get(i);  
  144.                     if (value.getName().contains(prefixString)) {  
  145.                         newValues.add(value);  
  146.                     }  
  147.                 }  
  148.  
  149.                 results.values = newValues;  
  150.                 results.count = newValues.size();  
  151.             }  
  152.  
  153.             return results;  
  154.         }  
  155.  
  156.         @SuppressWarnings("unchecked")  
  157.         @Override 
  158.         protected void publishResults(CharSequence constraint, FilterResults results) {  
  159.             mPersons = (ArrayList<UserInfo>) results.values;  
  160.             if (results.count > 0) {  
  161.                 notifyDataSetChanged();  
  162.             } else {  
  163.                 notifyDataSetInvalidated();  
  164.             }  
  165.         }  
  166.     }  
  167.  
  168.     static class ViewHolder {  
  169.         public TextView text1;  
  170.  
  171.         public TextView text2;  
  172.  
  173.         public ImageView imageView;  
  174.  
  175.         public CheckBox checkbox;  
  176.     }  
  177.  
  178. }  
  179.  

Activity中onCreate()裡的寫法:

  1. mSearchToolbar = (SearchToolbar) this.findViewById(R.id.top_search_toolbar);  
  2.    mListView = (ListView) this.findViewById(R.id.listview);  
  3.      
  4.    mDriverListAdapter = new UserListViewAdapter(this, driverList);  
  5.    mListView.setAdapter(mDriverListAdapter);  
  6.  
  7.    mSearchToolbar.setFilter(mDriverListAdapter.getFilter());  

SearchToolbar類的代碼:

  1. package com.easipass.custom.view;  
  2. import android.content.Context;  
  3. import android.text.Editable;  
  4. import android.text.TextWatcher;  
  5. import android.util.AttributeSet;  
  6. import android.view.LayoutInflater;  
  7. import android.view.View;  
  8. import android.widget.AutoCompleteTextView;  
  9. import android.widget.FrameLayout;  
  10. import android.widget.ImageView;  
  11. import android.widget.RelativeLayout;  
  12.  
  13. import com.easipass.R;  
  14.  
  15. /**  
  16.  * 功能描述:自定義搜索框組件  
  17.  * @author android_ls  
  18.  */ 
  19. public class SearchToolbar extends FrameLayout {  
  20.  
  21.     private RelativeLayout topSearchToolbar;  
  22.       
  23.     /**  
  24.      * 頂部自動補全文本輸入框  
  25.      */ 
  26.     private AutoCompleteTextView autoSearch;  
  27.  
  28.     /**  
  29.      * 清除搜索結果按鈕  
  30.      */ 
  31.     private ImageView btnClearSearch;  
  32.       
  33.     public SearchToolbar(Context context) {  
  34.         super(context);  
  35.         setupViews();  
  36.     }  
  37.  
  38.     public SearchToolbar(Context context, AttributeSet attrs) {  
  39.         super(context, attrs);  
  40.         setupViews();  
  41.     }  
  42.  
  43.     private void setupViews() {  
  44.         final LayoutInflater mLayoutInflater = LayoutInflater.from(getContext());  
  45.         topSearchToolbar = (RelativeLayout) mLayoutInflater.inflate(R.layout.top_search_toolbar, null);  
  46.         addView(topSearchToolbar);  
  47.           
  48.         btnClearSearch = (ImageView) topSearchToolbar.findViewById(R.id.iv_search_clear);  
  49.         autoSearch = (AutoCompleteTextView) topSearchToolbar.findViewById(R.id.auto_search);  
  50.     }  
  51.       
  52.     public void setFilter(final  android.widget.Filter filter) {  
  53.         autoSearch.addTextChangedListener(new TextWatcher() {  
  54.  
  55.             @Override 
  56.             public void onTextChanged(CharSequence s, int start, int before, int count) {  
  57.                 String filterWord = autoSearch.getText().toString().trim();  
  58.                 filter.filter(filterWord);  
  59.             }  
  60.  
  61.             @Override 
  62.             public void beforeTextChanged(CharSequence s, int start, int count, int after) {  
  63.                 // TODO Auto-generated method stub  
  64.  
  65.             }  
  66.  
  67.             @Override 
  68.             public void afterTextChanged(Editable s) {  
  69.                 // TODO Auto-generated method stub  
  70.  
  71.             }  
  72.         });  
  73.  
  74.         btnClearSearch.setOnClickListener(new View.OnClickListener() {  
  75.  
  76.             @Override 
  77.             public void onClick(View v) {  
  78.                 autoSearch.setText(null);  
  79.             }  
  80.         });  
  81.     }  
  82.       
  83. }  
  84.  

top_search_toolbar.xml文件:

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:id="@+id/top_search_bar" 
  4.     android:layout_width="match_parent" 
  5.     android:layout_height="45dip" 
  6.     android:background="@drawable/search_bar_bg" 
  7.     android:visibility="visible" > 
  8.     <AutoCompleteTextView 
  9.         android:id="@+id/auto_search" 
  10.         android:layout_width="fill_parent" 
  11.         android:layout_height="wrap_content" 
  12.         android:layout_centerVertical="true" 
  13.         android:layout_marginLeft="5dip" 
  14.         android:layout_marginRight="5dip" 
  15.         android:background="@drawable/search_bar_edit_normal" 
  16.         android:completionThreshold="1" 
  17.         android:drawableLeft="@drawable/search_bar_icon_normal" 
  18.         android:dropDownHorizontalOffset="30dip" 
  19.         android:dropDownVerticalOffset="9dip" 
  20.         android:dropDownWidth="210dip" 
  21.         android:singleLine="true" 
  22.         android:textSize="15sp" /> 
  23.  
  24.     <ImageView 
  25.         android:id="@+id/iv_search_clear" 
  26.         android:layout_width="wrap_content" 
  27.         android:layout_height="wrap_content" 
  28.         android:layout_alignParentRight="true" 
  29.         android:layout_centerVertical="true" 
  30.         android:layout_marginRight="12dip" 
  31.         android:layout_marginTop="-1dip" 
  32.         android:background="@drawable/btn_search_clear_selector" /> 
  33.  
  34. </RelativeLayout> 


 

轉自:http://blog.csdn.net/android_ls/article/details/8644247

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved