您的位置:首页 > 移动开发 > Android开发

Android 中使用ListView和CheckBox进行批量操作

2013-03-06 23:11 471 查看
在使用ListView时,一般为了性能的提升,都会使用ViewHolder,也就是Item的View实现复用。

现在的问题是,当在ListView的Item中包含CheckBox,并且CheckBox的事件处理监听器是holder.checkbox.setOnCheckedChangeListener()时,会出现第一项开始未选中,当第二项选中时第一项也跟着选中,这显然不是我们想要的结果。

出现这个问题的原因是第一项和第二项用的是同一个Item,当第二项选中时,CheckBox的当前状态为选中,这时setOnCheckedChangeListener里面会改变第一项关联的实体对象的属性(引用类型,变量A、B都引用同一个对象AA,当A把AA的某个属性值修改了,B再次访问时,AA对象的那个属性的值为A引用改后的值),代码如下:

holder.checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
driver.setSelected(isChecked);
}

});

解决办法:

1、在ListViewAdapter初始化时,将对象中有关CheckBox是否选中的属性存储起来。

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

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

3、在Adapter里的 public View getView(final int position, View convertView, ViewGroup parent){}方法体里面,当前的CheckBox是否选中状态,由之前初始化时保存的对象属性值控制,代码如下:

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

3、用户点击ListView的Item时,改变CheckBox的状态,代码如下:

convertView.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
checkbox.toggle();
selectedMap.put(position, checkbox.isChecked());
driver.setSelected(checkbox.isChecked());
}
});

数据适配器ListViewAdapter的完整代码:

package com.easipass.cloud.ccp.adapter;

import java.util.ArrayList;
import java.util.HashMap;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;

import com.easipass.R;
import com.easipass.cloud.ccp.entity.UserInfo;

/**
* 用户列表数据适配器
*
* @author android_ls
*/
public final class UserListViewAdapter extends BaseAdapter implements Filterable {
private LayoutInflater inflater;

private MyFilter myFilter;

private final Object mLock = new Object();

private ArrayList<UserInfo> mPersons;

private ArrayList<UserInfo> mCheckValues;

public HashMap<Integer, Boolean> selectedMap;

public UserListViewAdapter(Context context, ArrayList<UserInfo> cms) {
inflater = LayoutInflater.from(context);
mPersons = cms;

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

}

@Override
public int getCount() {
return mPersons.size();
}

@Override
public Object getItem(int arg0) {
return mPersons.get(arg0);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.ccp_carmanager_lv_item, null);
holder = new ViewHolder();
holder.text1 = (TextView) convertView.findViewById(R.id.tv_name);
holder.text2 = (TextView) convertView.findViewById(R.id.tv_phnoe);
holder.checkbox = (CheckBox) convertView.findViewById(R.id.checkbox);
holder.imageView = (ImageView) convertView.findViewById(R.id.iv_icon);

convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}

final UserInfo driver = mPersons.get(position);

holder.text1.setText(driver.getName());

holder.text2.setText(driver.getPhoneNumber());
// TODO 测试
holder.imageView.setBackgroundResource(Integer.valueOf(driver.getIconUrl()));
holder.checkbox.setVisibility(View.VISIBLE);

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

final CheckBox checkbox = holder.checkbox;
convertView.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
checkbox.toggle();
selectedMap.put(position, checkbox.isChecked());
driver.setSelected(checkbox.isChecked());
}
});

if (selected) {
convertView.setClickable(false);
}

return convertView;
}

@Override
public Filter getFilter() {
if (myFilter == null) {
myFilter = new MyFilter();
}
return myFilter;
}

class MyFilter extends Filter {

@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mCheckValues == null) {
synchronized (mLock) {
mCheckValues = new ArrayList<UserInfo>(mPersons);
}
}

if (prefix == null || prefix.length() == 0) {
synchronized (mLock) {
ArrayList<UserInfo> list = new ArrayList<UserInfo>(mCheckValues);
results.values = list;
results.count = list.size();
}
} else {
String prefixString = prefix.toString().toLowerCase();
final ArrayList<UserInfo> values = mCheckValues;
final int count = values.size();

final ArrayList<UserInfo> newValues = new ArrayList<UserInfo>(count);
for (int i = 0; i < count; i++) {
final UserInfo value = (UserInfo) values.get(i);
if (value.getName().contains(prefixString)) {
newValues.add(value);
}
}

results.values = newValues;
results.count = newValues.size();
}

return results;
}

@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mPersons = (ArrayList<UserInfo>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}

static class ViewHolder {
public TextView text1;

public TextView text2;

public ImageView imageView;

public CheckBox checkbox;
}

}

Activity中onCreate()里的写法:

mSearchToolbar = (SearchToolbar) this.findViewById(R.id.top_search_toolbar);
mListView = (ListView) this.findViewById(R.id.listview);

mDriverListAdapter = new UserListViewAdapter(this, driverList);
mListView.setAdapter(mDriverListAdapter);

mSearchToolbar.setFilter(mDriverListAdapter.getFilter());

SearchToolbar类的代码:

package com.easipass.custom.view;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AutoCompleteTextView;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.easipass.R;

/**
* 功能描述:自定义搜索框组件
* @author android_ls
*/
public class SearchToolbar extends FrameLayout {

private RelativeLayout topSearchToolbar;

/**
* 顶部自动补全文本输入框
*/
private AutoCompleteTextView autoSearch;

/**
* 清除搜索结果按钮
*/
private ImageView btnClearSearch;

public SearchToolbar(Context context) {
super(context);
setupViews();
}

public SearchToolbar(Context context, AttributeSet attrs) {
super(context, attrs);
setupViews();
}

private void setupViews() {
final LayoutInflater mLayoutInflater = LayoutInflater.from(getContext());
topSearchToolbar = (RelativeLayout) mLayoutInflater.inflate(R.layout.top_search_toolbar, null);
addView(topSearchToolbar);

btnClearSearch = (ImageView) topSearchToolbar.findViewById(R.id.iv_search_clear);
autoSearch = (AutoCompleteTextView) topSearchToolbar.findViewById(R.id.auto_search);
}

public void setFilter(final  android.widget.Filter filter) {
autoSearch.addTextChangedListener(new TextWatcher() {

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String filterWord = autoSearch.getText().toString().trim();
filter.filter(filterWord);
}

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// TODO Auto-generated method stub

}

@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub

}
});

btnClearSearch.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
autoSearch.setText(null);
}
});
}

}

top_search_toolbar.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/top_search_bar"
android:layout_width="match_parent"
android:layout_height="45dip"
android:background="@drawable/search_bar_bg"
android:visibility="visible" >
<AutoCompleteTextView
android:id="@+id/auto_search"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:background="@drawable/search_bar_edit_normal"
android:completionThreshold="1"
android:drawableLeft="@drawable/search_bar_icon_normal"
android:dropDownHorizontalOffset="30dip"
android:dropDownVerticalOffset="9dip"
android:dropDownWidth="210dip"
android:singleLine="true"
android:textSize="15sp" />

<ImageView
android:id="@+id/iv_search_clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="12dip"
android:layout_marginTop="-1dip"
android:background="@drawable/btn_search_clear_selector" />

</RelativeLayout>


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: