Android 中使用ListView和CheckBox进行批量操作
来源:互联网 发布:淘宝售后率怎么算 编辑:程序博客网 时间:2024/05/18 03:41
在使用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
>
- Android 中使用ListView和CheckBox进行批量操作
- Android 中使用ListView和CheckBox进行批量操作
- Android 中使用ListView和CheckBox进行批量操作
- 解决 Android 中使用ListView和CheckBox批量操作时若干问题
- 解决 Android 中使用ListView和CheckBox批量操作时若干问题
- 解决Android在listview中checkbox批量操作问题
- Android功能模块化之ListView中CheckBox批量操作
- android listview中checkbox(购物车,批量操作)
- 解决Android在listview中checkbox批量操作问题
- android listview中checkbox(购物车,批量操作)
- android listview中checkbox(购物车,批量操作)
- android listview中checkbox(购物车,批量操作)
- Android ListView和CheckBox应用之批量删除操作
- Android ListView和CheckBox应用之批量删除操作
- Android ListView和CheckBox应用之批量删除操作
- Android ListView和CheckBox应用之批量删除操作
- Android ListView和CheckBox应用之批量删除操作
- Android listview中使用checkbox
- IOSUITextView图文混排显示文本和表情
- XSS (Cross Site Scripting) Prevention Cheat Sheet
- 字符串分割--java中String.split()用法
- 黑马程序员——iOS 开发学习---类
- OpenTSDB 使用时 推荐配置
- Android 中使用ListView和CheckBox进行批量操作
- C#调用C++ Dll
- iOS - 小方法
- MyEclipse Eclipse安装SVN插件
- OpenTSDB TroubleShooting
- 归并排序
- POJ 2452 Sticks Problem(ST+二分查找)
- Android ScrollView嵌套ScrollView滚动的问题解决办法
- 自动优化mycncart和opencart所有数据库