【问题标题】:RecyclerView: how do I bind CheckBox state from ViewHolder to onBindViewHolder?RecyclerView:如何将 CheckBox 状态从 ViewHolder 绑定到 onBindViewHolder?
【发布时间】:2017-12-11 12:58:56
【问题描述】:

我有一个 CardView 的 RecyclerView 列表。每个 CardView 都有一个用户可以选择/取消选择的 CheckBox。初始选择启动上下文操作栏。整数的 ArrayList 用于保存复选框状态(选中或未选中)。滚动和复选框视图似乎工作正常。但是,当我单击一个复选框以取消选择它时,它仍然处于选中状态并且另一个 CardView 上的另一个复选框被取消选择?我在这里想念什么?

请注意,我不想在 onBindViewHolder 中设置 ClickListener。

MainActivity.java

public class MainActivity extends AppCompatActivity implements
    RecyclerItemClickListener {

    private ArrayList<ListItem> allList; 
    boolean isMultiSelect = false; // for the Contextual Action Bar status
    private ActionMode mActionMode;
    ArrayList<ListItem> multiselect_list = new ArrayList<>();
    private ArrayList<Integer> checkedListItems = new ArrayList<>();

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    ...

    // method from the Adapter, the ItemHolder's onClick()
    public void onCheckBoxClick(View view, int position) {

    if (!isMultiSelect) {
        multiselect_list = new ArrayList<>();
        isMultiSelect = true;

        if (mActionMode == null) {
            mActionMode = startSupportActionMode(actionModeCallback);                
        }
    }
    multi_select(position);
}

public void multi_select(int position) {

    if (mActionMode != null) {
        // If a CardView with a CheckBox already selected is clicked on, then the
        // Checkbox is unselected, the position is removed from the multiselect_list
        // and the size of the list is decremented by +1.
        if (multiselect_list.contains(allList.get(position))) {
            multiselect_list.remove(allList.get(position));
        }
        else {
            // If an empty CheckBox on a CardView is clicked on, then the position is added to the
            // multiselect_list and the size of the list is incremented by +1.
            multiselect_list.add(allList.get(position));
        }           
        if (multiselect_list.size() == 1) {
            mActionMode.setTitle("1 selected");
        }
        else if (multiselect_list.size() >= 2) {
            mActionMode.setTitle(multiselect_list.size() + " selected");
        }
        else if (multiselect_list.size() == 0) {
            mActionMode.finish();                
        }
        refreshAdapter();
    }
}

public void refreshAdapter() {
    adapter.selectedItemsList = multiselect_list;
    adapter.mListItems = allList;
    adapter.notifyDataSetChanged();
}

private ActionMode.Callback actionModeCallback = new ActionMode.Callback() {

    Menu context_menu;

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {

        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.menu_action_mode, menu);
        context_menu = menu;
        return true;
    }
    ...
} 

Adapter.java

public class MyRecylerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

public ArrayList<ListItem> mListItems;
private Context mContext;
private RecyclerItemClickListener recyclerItemClickListener; 
public ArrayList<ListItem> selectedItemsList = new ArrayList<>();

public MyRecylerAdapter(Context context, ArrayList<ListItem> listItems, ArrayList<ListItem> selectedList) {
    this.mContext = context;
    this.mListItems = listItems;
    this.selectedItemsList = selectedList;
} 

private class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    private CheckBox chkSelected;

    private ItemHolder(final View itemView) {
        super(itemView);

        chkSelected = (CheckBox) itemView.findViewById(R.id.chkSelected);
        chkSelected.setOnClickListener(this); 
    }  

    public void onClick(View v) {

        int adapterPos = getAdapterPosition();

        // send data to MainActivity() for starting CAB.
        if (recyclerItemClickListener !=null) {
            recyclerItemClickListener.onCheckBoxClick(v, adapterPos);
        }

        if (((CheckBox)v).isChecked()) {
            checkedListItems.add(adapterPos);
        }
        else {
            checkedListItems.remove(adapterPos);
        } 
    }    

    void bind(int position) { 

        if (checkedListItems.contains(position)) {
            chkSelected.setChecked(true);
        }
        else {
            chkSelected.setChecked(false);
        }    
    }
}    

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_contact_item, parent, false);
    final ItemHolder itemHolder = new ItemHolder(view);
    ...
    return itemHolder;
}

public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {

    final ListItem listItem = mListItems.get(position);
    final ItemHolder itemHolder = (ItemHolder) holder;

    itemHolder.bind(position);    
    ...
}

【问题讨论】:

    标签: checkbox android-recyclerview android-viewholder


    【解决方案1】:

    在 Adpater 中声明一个整数的 ArrayList

    ArrayList<Integer> checkedItems = new ArrayList();
    

    在绑定函数中

    void bind(int position) { 
    
        if (checkedItems.contains(position)) {
            chkSelected.setChecked(true);
        }
        else {
            chkSelected.setChecked(false);
        }
    }
    

    在 OnBindviewholder 中添加以下代码

    CompoundButton.OnCheckedChangeListener onCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            int adapterPos = getAdapterPosition();
            if(isChecked) {
                checkedItems.add(Integer.valueOf(adapterPos));
            }else {
                checkedItems.remove(Integer.valueOf(adapterPos));
            }
        }
    }
    

    【讨论】:

    • 我提到我不想在onBindViewholder方法中放置一个监听器。
    • @ajw 你也可以把这个监听器放在构造函数中
    • 好的。但是如何在 MainActivity 中构建一个 checkedItems 数组?
    • ArrayList checkedItems = new ArrayList();应该是适配器类的一部分。最初它是空的。
    • 声明checkedItems类似于public ArrayList selectedItemsList = new ArrayList();在适配器类中
    猜你喜欢
    • 2020-12-14
    • 2018-08-31
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 2021-01-17
    • 1970-01-01
    相关资源
    最近更新 更多