リストアイテムにチェックボックスが含まれているリストビューに問題があります。チェックボックスをオンにしてリストをスクロールすると、チェックボックスがオンチェックされた変更を自動的に呼び出すことがあり、チェックボックスの値が変更されます!
または、リストに9または10を超えるアイテムがある場合、アイテム1をチェックすると、アイテム8または9がチェックされますか?
誰でもこのバグを修正する方法を教えてくれますか?
前もって感謝します!
list_item.xml
<ImageView
Android:layout_alignParentLeft="true"
Android:layout_width="36dip"
Android:layout_height="36dip"
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_width="wrap_content"
Android:layout_height="wrap_content"
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_width="fill_parent"
Android:layout_height="wrap_content"
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;
}
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
を呼び出す前に。
_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);
}
}
});
_
リスト内のアイテムには、アイテムをチェックするかどうかを設定する属性があります。これを使用して、チェックされているかどうかを項目に設定できます。最初に、
_cBox.setOnCheckedChangeListener(null);
cBox.setChecked(list.get(position).isChecked());
_
次に、実際のnew OnCheckedChangeListener()
を設定します
私の答えがあなたやこのページを見たり、アイテムのチェックボックスがあるリストビューを扱うのに苦労している人たちに役立つことを願っています。
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);
}
});
これがきちんとした方法かどうかはわかりません。しかし、以下のコードは私の問題を解決しました。以下のコードでも、リストのスクロール時に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;
}
これらのほとんどはあまりにも複雑です(しかし、それらは機能します)。ビューがロードされている場合に.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
}
}
});