列表视图滚动时复选框自动调用onCheckedChange?
Posted
技术标签:
【中文标题】列表视图滚动时复选框自动调用onCheckedChange?【英文标题】:Checkbox auto call onCheckedChange when listview scroll? 【发布时间】:2011-08-31 07:50:50 【问题描述】:我对包含复选框的列表视图有疑问。当我选中一个框并滚动列表时,复选框有时会自动调用 oncheckedchange 并且复选框的值会更改!
或者,当我的列表有超过 9 或 10 项时,当我在第 1 项检查时,第 8 项或第 9 项被选中???
谁能告诉我如何解决这个错误?
提前致谢!
list_item.xml
<ImageView
android:layout_alignParentLeft="true"
android:layout_
android:layout_
android:layout_centerVertical="true"
android:scaleType="fitCenter"
android:id="@+id/image_view"
android:src="@drawable/icon" />
<TextView android:layout_toRightOf="@id/image_view"
android:layout_
android:layout_
android:paddingLeft="5dip"
android:id="@+id/text_view"
android:lines="1"
android:textSize="20sp"
android:textColor="@color/white" />
<TextView android:layout_toRightOf="@id/image_view"
android:layout_below="@id/text_view"
android:layout_
android:layout_
android:paddingLeft="5dip"
android:id="@+id/text_view2"
android:textSize="14sp"
android:lines="1"
android:textColor="@color/white" />
这是适配器视图:
public View getView(int position, View convertView, ViewGroup parent)
Log.e(TAG, "getView");
ViewHolder mViewHolder;
if (convertView == null)
Log.e(TAG, "Inflater is inflating...");
convertView = mInflater.inflate(R.layout.custom_list_app, null);
mViewHolder = new ViewHolder();
mViewHolder.checkbox = (CheckBox) convertView.findViewById(R.id.checkbox);
mViewHolder.remove = convertView.findViewById(R.id.music_info);
convertView.setTag(mViewHolder);
else
mViewHolder = (ViewHolder) convertView.getTag();
Log.e(TAG, "Position: " + position + " CheckBox: " + mViewHolder.checkbox.isChecked());
mViewHolder.checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton cb, boolean flag)
// TODO Auto-generated method stub
if (flag)
Log.d(TAG, "Checkbox checked");
else
Log.d(TAG, "Checkbox un-checked");
);
return convertView;
【问题讨论】:
【参考方案1】:ListView
回收视图类:您需要明确设置是否在 getView
类中选中 CheckBox。所以添加一个像
/**
* Ensure no other setOnCheckedChangeListener is attached before you manually
* change its state.
*/
mViewHolder.checkbox.setOnCheckedChangeListener(null);
if(shouldBeChecked) mViewHolder.checkbox.setChecked(true);
else mViewHolder.checkbox.setChecked(false);
在您致电setOnCheckedChangeListener
之前。
【讨论】:
所以我认为解决方案是这样的。当复选框被选中时,我使用一个数组来存储位置,并在调用 setOnCheckedChangeListener 之前检查位置被选中的位置。但是当我滚动列表(不检查)时,检查的位置发生了变化!我不明白为什么会这样 好吧,你应该总是打电话给setOnCheckedChangeListener
,但是你应该使用position
参数来告诉getView
是否应该选中复选框并每次都适当地更改它getView
被调用。
让我重复一遍:如果您要覆盖 getView
,则每次调用 getView
时都必须调用 setChecked(true)
或 setChecked(false)
。
费米,说得对。我错过了将 onchangelistner 设置为 null 的调用,并且更改的检查会自动触发。在设置值之前取消设置监听器是至关重要的。
我已经有一个星期的问题了!你救了我的命,先生。在执行 setChecked 以拥有重载方法或是否调用 onCheckChange 回调时有一个选项会很棒。只是说。【参考方案2】:
holder.cBox.setOnCheckedChangeListener(null);
holder.cBox.setChecked(list.get(position).isChecked());
holder.tvName.setText(item.getName());
holder.cBox.setOnCheckedChangeListener(new OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
if (isChecked)
list.get(position).setChecked(true);
else
list.get(position).setChecked(false);
);
在列表中,item 有一个属性来设置item 是否被选中。您可以使用它来设置您的项目是否选中,首先您应该设置
cBox.setOnCheckedChangeListener(null);
cBox.setChecked(list.get(position).isChecked());
然后设置真正的new OnCheckedChangeListener()
我希望我的回答对您和那些查看此页面或在处理带有项目复选框的列表视图时遇到问题的人有用。
【讨论】:
【参考方案3】:我不确定这是否是一种简洁的方式。但是下面的代码解决了我的问题。即使在下面的代码中,在滚动列表时也会调用 setOnCheckChangeListener()(读取错误触发)。任务是维护用户选择的项目列表。因此,当有触发器时,我首先引用我的列表,并且仅在列表中不存在该项目时才添加该项目,否则我将忽略回调。
@Override
public View getView(final int position, View convertView, final ViewGroup parent)
MenuViewHolder menuViewHolder = null;
MenuView item = getItem(position);
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(R.layout.food_menu_list_layout, null);
TextView textView = ((TextView) convertView.findViewById(R.id.menu_item_entry));
TextView price = (TextView) convertView.findViewById(R.id.price);
CheckBox ordered = (CheckBox) convertView.findViewById(R.id.checkBox);
menuViewHolder = new MenuViewHolder(textView, price, ordered);
menuViewHolder.dishName.setText(menuViewList.get(position).getItemname());
menuViewHolder.price.setText("$" + menuViewList.get(position).getPrice());
menuViewHolder.ordered.setChecked(menuViewList.get(position).isSelected());
menuViewHolder.ordered.setOnCheckedChangeListener(null);
menuViewHolder.ordered.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
MenuView checkedItem = menuViewList.get(position);
if (buttonView.isChecked())
//add item only if not already added
if (!checkedItem.isSelected())
MainActivity.menuViews.add(checkedItem);
checkedItem.setSelected(buttonView.isChecked());
else
//remove only if already added
if (checkedItem.isSelected())
MainActivity.menuViews.remove(checkedItem);
checkedItem.setSelected(buttonView.isChecked());
((MainActivity) context).displayCurrentSelectionAmt();
);
return convertView;
【讨论】:
【参考方案4】:其中大多数都过于复杂(但它们确实有效)。如果正在加载视图并设置检查状态,您要做的就是停止触发 .setChecked 事件。所以,设置一个局部类变量isLoading,在getView开始时设置为true,在getView结束时设置为false。然后在点击监听中,勾选isLoading
boolean isLoading;
public View getView(int position, View convertView, ViewGroup parent)
isLoading = true;
...do your initialization here
isLoading = false;
return convertView;
checkview.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton pckView, boolean pisChecked)
if(! isLoading)
...do your things when the check is actually clicked
);
【讨论】:
【参考方案5】:OnClickListener 为我解决了同样的问题,我可以将数据发送到另一个活动
holder.cks.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
final boolean isChecked = holder.cks.isChecked();
if (isChecked)
System.out.println(position + "Checked");
holder.cks.setChecked(true);
positionArray.set(position, true);
DATA2="1";
else
System.out.println(position + "unChecked");
holder.cks.setChecked(false);
positionArray.set(position, false);
DATA2 = "0";
DATA1=String.valueOf(position+1);
DATA3=map.get(COL5);
DATA4=map.get(COL6);
DATA5=map.get(COL7);
Intent intent = new Intent(activity, updatelicaldata.class);
intent.putExtra("message1", DATA1);
intent.putExtra("message2", DATA2);
intent.putExtra("message3", DATA3);
intent.putExtra("message4", DATA4);
intent.putExtra("message5", DATA5);
System.out.println("ACTIVITY IS START");
activity.startActivity(intent);
);
【讨论】:
以上是关于列表视图滚动时复选框自动调用onCheckedChange?的主要内容,如果未能解决你的问题,请参考以下文章