【问题标题】:Android: Checking one CheckBox checks all CheckBoxes in the same rowAndroid:选中一个复选框会检查同一行中的所有复选框
【发布时间】:2018-10-01 18:21:20
【问题描述】:

我的应用显示ListView,每个row 的CheckBoxes 数量不同。一行的CheckBoxes 的最大数量是三个。我的应用看起来像这样:

  1. 如果左边的CheckBox 被选中,那么右边的所有CheckBoxes 都应该被自动选中。
  2. 如果右侧的CheckBox 未选中,则左侧的所有CheckBoxes 都应自动取消选中。

我将在这里举一个小例子:
第一行有三个CheckBoxes (cb1, cb2 and cb3)。 cb1 在左侧,cb2 在中间,cb3 在右侧。

  1. 所有CheckBoxes 当前都未选中。用户检查左边的 (cb1)。所有其他 CheckBoxes (cb2 and cb3) 都会被自动检查。
  2. 当前检查所有CheckBoxes。用户取消选中正确的 (cb3)。 所有其他CheckBoxes (cb1 and cb2) 都将自动取消选中。

我尝试使用OnCheckedChangeListener 解决我的问题,但出现以下消息

“变量'Holder'是从内部类中访问的,需要 被宣布为最终的。”

我的问题:

  1. 如何解决这个问题,使 Message 不会出现?

  2. 我的解决方案在逻辑上正确吗?

如果我的问题不清楚,请发表评论。

我的解决方案:

 holder.cb1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                 @Override
                 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                     buttonView.setChecked(isChecked);
                     //Case1: Left (cb1) gets checked -> set all other right CB´s (cb2 & cb3) checked
                     if(isChecked){
                         holder.cb2.setChecked(isChecked);  //Error Message occurs here
                         holder.cb3.setChecked(isChecked);  //Error Message occurs here
                     }
                   }
               });

            holder.cb2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    buttonView.setChecked(isChecked);
                    //Case2: Middle (cb2) gets checked -> set right CB (cb3) checked
                    if(isChecked){
                        holder.cb3.setChecked(isChecked);   //Error Message occurs here
                    }
                    //Case3: Middle (cb2) gets unchecked -> set left CB (cb1) unchecked
                    else {
                        holder.cb1.setChecked(isChecked);   //Error Message occurs here
                    }
                  }
              });

            holder.cb3.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    buttonView.setChecked(isChecked);
                    //Case4: Right (cb3) gets unchecked -> set all other left CB´s (cb1 & cb 2) unchecked
                    if(!isChecked){
                        holder.cb2.setChecked(isChecked);   //Error Message occurs here
                        holder.cb1.setChecked(isChecked);   //Error Message occurs here
                    }
                  }
              });

自定义适配器:

public class ItemListAdapter extends BaseAdapter {

private LayoutInflater inflater;
private ArrayList<Object> itemArray;
int resIdImage;
private static final int TYPE_ListElement = 0;
private static final int TYPE_DIVIDER = 1;

public ItemListAdapter(Context context, ArrayList<Object> itemArray, int resource) {
    this.itemArray = itemArray;
    this.resIdImage = resource;
    this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

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

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

@Override
public Object getItem(int position) {
    return itemArray.get(position);
}

@Override
public int getViewTypeCount() {
    // TYPE_PERSON and TYPE_DIVIDER
    return 2;
}

@Override
public int getItemViewType(int position) {
    if (getItem(position) instanceof ItemList) {
        return TYPE_ListElement;
    }

    return TYPE_DIVIDER;
}

@Override
public boolean isEnabled(int position) {
    return (getItemViewType(position) == TYPE_ListElement);
}

public class DataHolder{
    ImageView imageView;
    TextView textView;
    CheckBox cb1;
    CheckBox cb2;
    CheckBox cb3;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {

    DataHolder holder =  null;
    int type = getItemViewType(position);
    if (convertView == null) {
        switch (type) {
            case TYPE_ListElement:
                convertView = inflater.inflate(resIdImage, parent, false);
                holder = new DataHolder();
                holder.imageView = (ImageView) convertView.findViewById(R.id.image);
                holder.textView = (TextView) convertView.findViewById(R.id.nameLabel);
                holder.cb1 = (CheckBox) convertView.findViewById(R.id.checkbox);
                holder.cb2 = (CheckBox) convertView.findViewById(R.id.checkbox2);
                holder.cb3 = (CheckBox) convertView.findViewById(R.id.checkbox3);
                convertView.setTag(holder);
                break;
            case TYPE_DIVIDER:
                convertView = inflater.inflate(R.layout.row_header, parent, false);
                break;
        }
    }
    else {
        holder = (DataHolder)convertView.getTag();
    }

    switch (type) {
        case TYPE_ListElement:
            ItemList item = (ItemList) getItem(position);
            holder.textView.setText(item.getTitle());
            holder.imageView.setImageResource(item.resIdImage);

            int numCheckBox = item.numCheckBox;
            if(numCheckBox == 1){
               holder.cb1.setVisibility(View.VISIBLE);
               holder.cb2.setVisibility(View.GONE);
               holder.cb3.setVisibility(View.GONE);
            } else if (numCheckBox == 2){
               holder.cb1.setVisibility(View.VISIBLE);
               holder.cb2.setVisibility(View.VISIBLE);
               holder.cb3.setVisibility(View.GONE);
            } else if (numCheckBox == 3){
               holder.cb1.setVisibility(View.VISIBLE);
               holder.cb2.setVisibility(View.VISIBLE);
               holder.cb3.setVisibility(View.VISIBLE);
            }
             holder.cb1.setChecked(item.checked);
             holder.cb2.setChecked(item.checked);
             holder.cb3.setChecked(item.checked);

             holder.cb1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                 @Override
                 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                     buttonView.setChecked(isChecked);
                     //Case1: Left (cb1) gets checked -> set all other right CB´s (cb2 & cb3) checked
                     if(isChecked){
                         holder.cb2.setChecked(isChecked);  //Error Message occurs here
                         holder.cb3.setChecked(isChecked);  //Error Message occurs here
                     }
                 }
             });

            holder.cb2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    buttonView.setChecked(isChecked);
                    //Case2: Middle (cb2) gets checked -> set right CB (cb3) checked
                    if(isChecked){
                        holder.cb3.setChecked(isChecked);   //Error Message occurs here
                    }
                    //Case3: Middle (cb2) gets unchecked -> set left CB (cb1) unchecked
                    else {
                        holder.cb1.setChecked(isChecked);   //Error Message occurs here
                    }
                }
            });

            holder.cb3.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    buttonView.setChecked(isChecked);
                    //Case4: Right (cb3) gets unchecked -> set all other left CB´s (cb1 & cb 2) unchecked
                    if(!isChecked){
                        holder.cb2.setChecked(isChecked);   //Error Message occurs here
                        holder.cb1.setChecked(isChecked);   //Error Message occurs here
                    }
                }
            });

             break;

        case TYPE_DIVIDER:
            TextView title = (TextView)convertView.findViewById(R.id.headerTitle);
            String titleString = (String)getItem(position);
            title.setText(titleString);
            break;
    }


    return convertView;
}
}

行布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<ImageView
    android:id="@+id/image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@mipmap/ic_launcher"
    android:layout_gravity="center"
    android:layout_margin="20dp"/>

<TextView
    android:id="@+id/nameLabel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="20sp"
    android:layout_margin="20dp"
    android:text="Name"
    android:layout_weight="1"
/>

<CheckBox
    android:id="@+id/checkbox"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:checked="false"
    android:focusable="false"
    android:focusableInTouchMode="false"
    android:layout_gravity="right|center"
    android:gravity="right|center"
    />

<CheckBox
    android:id="@+id/checkbox2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:checked="false"
    android:focusable="false"
    android:focusableInTouchMode="false"
    android:layout_gravity="right|center"
    android:gravity="right|center"
    />

<CheckBox
    android:id="@+id/checkbox3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:checked="false"
    android:focusable="false"
    android:focusableInTouchMode="false"
    android:layout_gravity="right|center"
    android:gravity="right|center"
    />

</LinearLayout>

【问题讨论】:

    标签: java android listview checkbox


    【解决方案1】:

    创建一个引用您ViewHolder 的final 变量并在您的onCheckedChangeListener 内部使用它:

    final DataHolder finalHolder = holder;
    
    holder.cb1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                 @Override
                 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                     buttonView.setChecked(isChecked);
                     //Case1: Left (cb1) gets checked -> set all other right CB´s (cb2 & cb3) checked
                     if(isChecked){
                         finalHolder.cb2.setChecked(isChecked);  // NO MORE ERROR
                         finalHolder.cb3.setChecked(isChecked);  //NO MORE ERROR
                     }
                 }
             });
    
    holder.cb2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    buttonView.setChecked(isChecked);
                    //Case2: Middle (cb2) gets checked -> set right CB (cb3) checked
                    if(isChecked){
                        finalHolder.cb3.setChecked(isChecked);   // NO MORE ERROR
                    }
                    //Case3: Middle (cb2) gets unchecked -> set left CB (cb1) unchecked
                    else {
                        finalHolder.cb1.setChecked(isChecked);   //NO MORE ERROR
                    }
                }
            });
    

    对 cb3 onCheckedChangeListener 也这样做。

    【讨论】:

      猜你喜欢
      • 2012-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多