我有一个listView片段,listview布局包含(TextView,checkBox和ImageView如下
t1........CB.......IV
t2........CB.......IV
t3........CB.......IV
t4........CB.......IV
t5........CB.......IV
t6........CB.......IV
SaveButton
在getView()方法中,我检查是否选中了复选框,如果选中它,我将选中的项添加到列表中。
问题在于,最初我将所有复选框设置为未选中,但是当我检查第一项时,令人惊讶的是,自动检查下面的第三项,如果我从上面检查第二项,则第二项从下面检查,如果我检查上面的第3项,然后自动检查最后一项?!!
请查看getView()方法,让我知道错过了什么:
getView():
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if (convertView == null) {
LayoutInflater layoutinflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = layoutinflater.inflate(R.layout.list_items_layout, null);
}
if (this.checkedItemsList == null) {
this.checkedItemsList = new ArrayList<String>();
}
final TextView tv = (TextView) convertView.findViewById(R.id.tvlist_topic);
final CheckBox cb = (CheckBox) convertView.findViewById(R.id.cbList_hook);
final ImageView iv = (ImageView) convertView.findViewById(R.id.ivList_delete);
tv.setText(this.topicsList.get(position));
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked) {
checkedItemsList.add(topicsList.get(position));
setCheckedItemsList(checkedItemsList);
Log.d(TAG, "size: " + checkedItemsList.size());
}
}
});
iv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (cb.isChecked())
cb.setChecked(false);
topicsList.remove(position);
notifyDataSetChanged();
}
});
return convertView;
}
XML :
<RelativeLayout
android:id="@+id/rl2_List"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/rl1_List"
android:layout_centerInParent="true">
<CheckBox
android:id="@+id/cbList_hook"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:focusableInTouchMode="false"
android:checked="false"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/rl3_List"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/rl2_List"
android:layout_alignParentEnd="true"
android:layout_marginStart="100dp">
<ImageView
android:id="@+id/ivList_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="true"
android:src="@drawable/delete_icon"
android:contentDescription="icon to delete item from the Listview"/>
</RelativeLayout>
答案 0 :(得分:1)
您必须保持对象检查状态。
我会在你的对象(在topicsList中)实现一个实例变量,它指示是否检查过它。
像
这样的东西public class Topic{
public boolean isChecked;
... //Other instance variables
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean isChecked) {
this.isChecked = isChecked;
}
...
//other getters and setters
}
然后在listAdapter getView
方法中,检查此值并相应地设置复选框。
final CheckBox cb = (CheckBox) convertView.findViewById(R.id.cbList_hook);
boolean isChecked = topicsList.get(position).isChecked();
cb.setChecked(isChecked);
//Set a tag on the cb, to know which object it corresponds with
cb.setTag(topicsList.get(position));
此外,您必须在点击时更改对象检查值。
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked) {
checkedItemsList.add(topicsList.get(position));
setCheckedItemsList(checkedItemsList);
Log.d(TAG, "size: " + checkedItemsList.size());
}
CheckBox cb = (CheckBox) buttonView;
Object yourObject = (Object) buttonView.getTag();
yourObject.setChecked(isChecked);
}
});
答案 1 :(得分:0)
您需要了解convertView
,这对初学者来说往往更加困惑。
例如,如果您在一个巨大的列表中有100个复选框,但屏幕上一次只能看到5个,那么天真的方法是为Checkbox创建100个对象(实际上这是它在早期版本的Android中的工作方式) 。但是,创建新对象不仅会在创建过程中耗费CPU,还会在垃圾收集期间耗费CPU。这就是使用convertView的原因。 Android系统将仅创建5个对象,并在用户滚动时重用相同的对象。在您的情况下,我认为屏幕上只有3个对象。因此,从技术上讲,滚出屏幕的第一个对象和屏幕上显示的第四个对象是相同的。
您的解决方案是将View
个对象视为可视元素,并将状态保存在其他位置。我认为另一个答案建议代码,因此,我将避免建议代码并鼓励您理解这个概念并自己找出解决方案。
答案 2 :(得分:0)
你必须做这样的事情
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if (convertView == null) {
LayoutInflater layoutinflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = layoutinflater.inflate(R.layout.list_items_layout, null);
}
if (this.checkedItemsList == null) {
this.checkedItemsList = new ArrayList<String>();
}
final TextView tv = (TextView) convertView.findViewById(R.id.tvlist_topic);
final CheckBox cb = (CheckBox) convertView.findViewById(R.id.cbList_hook);
final ImageView iv = (ImageView) convertView.findViewById(R.id.ivList_delete);
tv.setText(this.topicsList.get(position));
cb.setTag(position);
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked) {
checkedItemsList.add(topicsList.get(Integer.parseInt(buttonView.getTag().toString())));
setCheckedItemsList(checkedItemsList);
Log.d(TAG, "size: " + checkedItemsList.size());
}
}
});
return convertView;
}
答案 3 :(得分:0)
如果使用ViewHolder模式会更好。每次用户滚动列表时,它将防止膨胀视图的开销。此外,是否应选中复选框应存在于数据源中(用于填充ListView的数据结构;在本例中为topicsList)。假设数据结构的模型类名为Model:
public class Model {
private boolean mChecked = false;
public boolean isChecked() {
return this.mChecked;
}
public void setChecked(boolean checked) {
this.mChecked = checked;
}
}
现在在ListView的适配器类
中public class SomeAdapter extends BaseAdapter {
private ArrayList<Model> topicsList; //assuming this is filled with data
static class ViewHolder { //the view holder's class
TextView text;
CheckBox checkBox;
ImageView imageView;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder;
if (convertView == null) {
LayoutInflater layoutinflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = layoutinflater.inflate(R.layout.list_items_layout, null);
TextView tv = (TextView) convertView.findViewById(R.id.tvlist_topic);
CheckBox cb = (CheckBox) convertView.findViewById(R.id.cbList_hook);
ImageView iv = (ImageView) convertView.findViewById(R.id.ivList_delete);
holder = new ViewHolder();
holder.textView = tv;
holder.checkBox = cb;
holder.imageView = iv;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) converView.getTag();
}
if (this.checkedItemsList == null) {
this.checkedItemsList = new ArrayList<String>();
}
TextView textView = viewHolder.textView;
CheckBox checkBox = viewHolder.checkBox;
ImageView imageView = viewHolder.imageView;
textView.setText(this.topicsList.get(position));
if (this.topicsList.get(position).isChecked()) {
checkBox.setChecked(true);
} else {
checkBox.setChecked(false);
}
checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked) {
SomeAdapter.this.topicsList.get(position).setChecked(isChecked);
checkedItemsList.add(SomeAdapter.this.topicsList.get(position));
setCheckedItemsList(checkedItemsList);
Log.d(TAG, "size: " + checkedItemsList.size());
}
}
});
imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (checkBox.isChecked()) {
checkBox.setChecked(false);
SomeAdapter.this.topicsList.get(position).setChecked(false);
topicsList.remove(position);
notifyDataSetChanged();
} else { //if needed
checkBox.setChecked(true);
SomeAdapter.this.topicsList.get(position).setChecked(true);
//perform other operations here
}
}
});
return convertView;
}
}