如何在RecyclerView中实现复选框的单选?

huangapple go评论57阅读模式
英文:

how to have single choice on checkbox in recyclerview?

问题

以下是您提供的内容的中文翻译:

我有一个包含每个项目内部复选框的 RecyclerView,我希望用户只能选择一个项目。

我测试过的解决方案没有选中复选框。

我看到许多解决方案,但我测试过的解决方案得分较高。

它必须自动执行此操作。

我应该怎么做?

我不想使用 RadioGroup。

提前感谢您。

DeveloperAdapter 代码:


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

    private List<DeveloperEntity> developerEntities;
    private Context context;
    ArrayList<Boolean> positionArray;

    public DeveloperAdapter(List<DeveloperEntity> developerEntities, Context context) {
        this.developerEntities = developerEntities;
        this.context = context;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.developer_adapter, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        final DeveloperEntity developerEntity = developerEntities.get(position);
        holder.mTxtName.setText(developerEntity.getName());
        holder.mTxtPosition.setText(developerEntity.getPosition());

        Drawable drawable = new BitmapDrawable(Utility.byteArrayToBitmap(developerEntity.getImg()));
        holder.mImgPhoto.setImageDrawable(drawable);
        holder.mImgPhoto.setImageBitmap(BitmapFactory.decodeByteArray(developerEntity.getImg(), 0, developerEntity.getImg().length));

        setEditRemove(holder, position, developerEntity);

        try {
            developerEntities = DatabaseManager.getDatabaseHelper(context).getDeveloperDao().queryForAll();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        positionArray = new ArrayList<Boolean>(developerEntities.size());
        for (int i = 0; i < developerEntities.size(); i++) {
            positionArray.add(false);
        }
    }

    private void setEditRemove(final ViewHolder holder, final int position, final DeveloperEntity developerEntity) {
        holder.mImgRemove.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AlertDialog alertDialog = new AlertDialog.Builder(context)
                        .setTitle("Delete User")
                        .setMessage("Are you sure to delete this user?")
                        .setPositiveButton("Delete", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                presentAlertDelete(holder.getAdapterPosition(), developerEntity.getId());
                            }
                        })
                        .setNegativeButton("No", null)
                        .create();
                alertDialog.show();
            }
        });

        holder.mImgEdit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(context, AddDeveloperActivity.class);
                intent.putExtra("id", developerEntity.getId());
                context.startActivity(intent);
            }
        });

        holder.chkIsChecked.setOnCheckedChangeListener(null);
        if (positionArray != null) {
            holder.chkIsChecked.setChecked(positionArray.get(position));
        }

        holder.chkIsChecked.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    positionArray.set(position, true);
                } else {
                    positionArray.set(position, false);
                }
            }
        });

        Log.i("", "" + positionArray);
    }

    private void presentAlertDelete(int adapterPosition, long id) {
        try {
            DatabaseManager.getDatabaseHelper(context).getDeveloperDao().deleteById(id);
            developerEntities.remove(adapterPosition);
            notifyItemRemoved(adapterPosition);
            notifyItemChanged(adapterPosition, developerEntities.size());
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private void deleteUser(int adapterPosition) {
        developerEntities.remove(adapterPosition);
        notifyItemRemoved(adapterPosition);
        notifyItemChanged(adapterPosition, developerEntities.size());
    }

    @Override
    public int getItemCount() {
        return developerEntities == null ? 0 : developerEntities.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        private CircleImageView mImgPhoto;
        private TextView mTxtName;
        private TextView mTxtPosition;
        private ImageView mImgEdit;
        private ImageView mImgRemove;
        private CheckBox chkIsChecked;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            initView(itemView);
        }

        private void initView(@NonNull final View itemView) {
            mImgPhoto = (CircleImageView) itemView.findViewById(R.id.imgPhoto);
            mTxtName = (TextView) itemView.findViewById(R.id.txtName);
            mTxtPosition = (TextView) itemView.findViewById(R.id.txtPosition);
            mImgEdit = (ImageView) itemView.findViewById(R.id.imgEdit);
            mImgRemove = (ImageView) itemView.findViewById(R.id.imgRemove);
            chkIsChecked = itemView.findViewById(R.id.chkIsChecked);
        }
    }
}
英文:

I have a recyclerview that has a checkbox inside each item and I want the user to be able to check only one item.

The solution I tested does not pick up the check.

I saw many solutions that the one I tested had a higher score.

It has to do this automatically.

What should I do?

I don't want to use RadioGroup

Thanks in advance.

DeveloperAdapter codes:


public class DeveloperAdapter extends RecyclerView.Adapter&lt;DeveloperAdapter.ViewHolder&gt; {

    private List&lt;DeveloperEntity&gt; developerEntities;
    private Context context;
    ArrayList&lt;Boolean&gt; positionArray;



    public DeveloperAdapter(List&lt;DeveloperEntity&gt; developerEntities, Context context) {
        this.developerEntities = developerEntities;
        this.context = context;
    }


    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.developer_adapter, parent, false);
        return new ViewHolder(view);
    }


    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

        final DeveloperEntity developerEntity = developerEntities.get(position);
        holder.mTxtName.setText(developerEntity.getName());
        holder.mTxtPosition.setText(developerEntity.getPosition());

        Drawable drawable = new
                BitmapDrawable(Utility.byteArrayToBitmap(developerEntity.getImg()));
        holder.mImgPhoto.setImageDrawable(drawable);
        holder.mImgPhoto.setImageBitmap(BitmapFactory.decodeByteArray(developerEntity.getImg(), 0, developerEntity.getImg().length));

        setEditRemove(holder, position, developerEntity);

        try {
            developerEntities=DatabaseManager.getDatabaseHelper(context).getDeveloperDao().queryForAll();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        positionArray = new ArrayList&lt;Boolean&gt;(developerEntities.size());
        for(int i =0;i&lt;developerEntities.size();i++){
            positionArray.add(false);
        }
    }

    private void setEditRemove(final ViewHolder holder, final int position, final DeveloperEntity developerEntity) {
        holder.mImgRemove.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AlertDialog alertDialog = new AlertDialog.Builder(context)
                        .setTitle(&quot;Delete User&quot;)
                        .setMessage(&quot;Are you sure to delete this user?&quot;)
                        .setPositiveButton(&quot;Delete&quot;, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                presentAlertDelete(holder.getAdapterPosition(), developerEntity.getId());
                            }
                        })
                        .setNegativeButton(&quot;No&quot;, null)
                        .create();
                alertDialog.show();

            }
        });
        holder.mImgEdit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(context, AddDeveloperActivity.class);
                intent.putExtra(&quot;id&quot;, developerEntity.getId());
                context.startActivity(intent);

            }
        });

        holder.chkIsChecked.setOnCheckedChangeListener(null);
        if (positionArray!= null){
            holder.chkIsChecked.setChecked(positionArray.get(position));

        }


        holder.chkIsChecked.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(isChecked ){
                    positionArray.set(position, true);

                }else
                    positionArray.set(position, false);
            }


        });
        Log.i(&quot;&quot;,&quot;&quot;+positionArray);






    }

    private void presentAlertDelete(int adapterPosition, long id) {
        try {
            DatabaseManager.getDatabaseHelper(context).getDeveloperDao().deleteById(id);
            developerEntities.remove(adapterPosition);
            notifyItemRemoved(adapterPosition);
            notifyItemChanged(adapterPosition, developerEntities.size());
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private void deleteUser(int adapterPosition) {
        developerEntities.remove(adapterPosition);
        notifyItemRemoved(adapterPosition);
        notifyItemChanged(adapterPosition, developerEntities.size());
    }


    @Override
    public int getItemCount() {
        return developerEntities == null ? 0 : developerEntities.size();
        //  return  userItemDeveloperDBS.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        private CircleImageView mImgPhoto;
        private TextView mTxtName;
        private TextView mTxtPosition;
        private ImageView mImgEdit;
        private ImageView mImgRemove;
        private CheckBox chkIsChecked;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            initView(itemView);
        }

        private void initView(@NonNull final View itemView) {
            mImgPhoto = (CircleImageView) itemView.findViewById(R.id.imgPhoto);
            mTxtName = (TextView) itemView.findViewById(R.id.txtName);
            mTxtPosition = (TextView) itemView.findViewById(R.id.txtPosition);
            mImgEdit = (ImageView) itemView.findViewById(R.id.imgEdit);
            mImgRemove = (ImageView) itemView.findViewById(R.id.imgRemove);
            chkIsChecked = itemView.findViewById(R.id.chkIsChecked);
        }
    }
}

答案1

得分: 2

你应该为传递给你的适配器的列表中的每个值定义一个状态。通过这个状态,你可以决定哪个复选框应该被选中,哪个不应该被选中。当适配器中的项目发生更改时,你必须通过活动中的监听器收到通知,并对列表中每个项目的状态进行更改。
在此之后,只需要简单地调用adapter.notifyDataSetChanged()就可以使一切正常!

以下是示范代码:

活动部分大致如下:

class MainActivity : AppCompatActivity(), Adapter.OnItemClick {

    private val items = ArrayList<ListItems>()

    private lateinit var adapter: Adapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(findViewById(R.id.toolbar))

        items.add(ListItems(0, isChecked: false, checkable: true))
        items.add(ListItems(1, isChecked: false, checkable: true))
        items.add(ListItems(2, isChecked: false, checkable: true))

        adapter = Adapter(items, this)
        recyclerView.adapter = adapter
        recyclerView.layoutManager = LinearLayoutManager(this)
    }

    override fun onItemClicked(position: Int, state: Boolean) {
        Log.i("MainActivity", "onItemClicked: position :")
        items[position].state = state
        if (!state) {
            for (item in items) {
                item.checkable = true
            }
        } else {
            for (x in 0 until items.size) {
                items[x].checkable = x == position
            }
        }
        adapter.notifyDataSetChanged()
    }
}

适配器类部分大致如下:

class Adapter(val items: ArrayList<ListItems>, val onItemClick: OnItemClick) :
    RecyclerView.Adapter<Adapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(parent.context).inflate(R.layout.item_adapter, parent, false)
        )
    }

    override fun getItemCount(): Int {
        return items.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val checkBox = holder.itemView.findViewById<CheckBox>(R.id.checkbox)
        checkBox.isChecked = items[position].state
        checkBox.isEnabled = items[position].editable
        checkBox.setOnCheckedChangeListener(object :
            CompoundButton.OnCheckedChangeListener {
            override fun onCheckedChanged(p0: CompoundButton?, check: Boolean) {
                if (check) {
                    onItemClick.onItemClicked(position, true)
                } else {
                    onItemClick.onItemClicked(position, false)
                }
            }
        })
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    }

    interface OnItemClick {
        fun onItemClicked(position: Int, state: Boolean)
    }
}
英文:

you should define a state for each value of your list that you passed to your adapter.whit this state you can decide which checkbox must be checked or not. when a change occurs in items of adapter you must be notified with a listener in your activity and made a change to the state of each item of the list.
after that, just a simple adapter.notifyDataSetChanged() can make everything ok!

I try to make it clear with the sample code below :

Activity is something like this :

class MainActivity : AppCompatActivity(), Adapter.OnItemClick {

private val items = ArrayList&lt;ListItems&gt;()

private lateinit var adapter: Adapter

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setSupportActionBar(findViewById(R.id.toolbar))

    items.add(ListItems(0, isChecked : false, checkable : true))
    items.add(ListItems(1, isChecked : false, checkable : true))
    items.add(ListItems(2, isChecked : false, checkable : true))

    adapter = Adapter(items, this)
    recyclerView.adapter = adapter
    recyclerView.layoutManager = LinearLayoutManager(this)



}


override fun onItemClicked(position: Int, state: Boolean) {
    Log.i(&quot;MainActivity&quot;, &quot;onItemClicked: position :&quot;)
    items.get(position).state = state
    if (!state) {
        for (item in items) {
            item.checkable = true
        }
    } else {
        for (x in 0 until items.size) {
            items.get(x).checkable = x == position

        }
    }

    adapter.notifyDataSetChanged()


 }

and the adapter class :

class Adapter(val items: ArrayList<ListItems>, val onItemClick: OnItemClick) :
RecyclerView.Adapter<Adapter.ViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    return ViewHolder(
        LayoutInflater.from(parent.context).inflate(R.layout.item_adapter, parent, false)
    )
}

override fun getItemCount(): Int {
    return items.size
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val checkBox = holder.itemView.findViewById&lt;CheckBox&gt;(R.id.checkbox)
    checkBox.isChecked = items.get(position).state
    checkBox.isEnabled = items.get(position).editable
    checkBox.setOnCheckedChangeListener(object : 
       CompoundButton.OnCheckedChangeListener {
        override fun onCheckedChanged(p0: CompoundButton?, check: 
               Boolean) {
            if (check) {
                onItemClick.onItemClicked(position, true)
            } else
                onItemClick.onItemClicked(position, false)
        }
    })
}

class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
}

interface OnItemClick {
    fun onItemClicked(position: Int, state: Boolean)
}

}

答案2

得分: 0

这是我在我的应用程序中经常使用的解决方案。当您点击项目时,请调用此函数:

private fun removeAll(position: Int) {
    for (value in mListYourData) {
        value.isSelected = false
    }
    mListYourData[position].isSelected = true
    notifyDataSetChanged()
}
英文:

This is solution I alway use in my app. When you click item, call this function:

private fun removeAll(position: Int) {
        for (value in mListYourData) {
            value.isSelected = false
        }
        mListYourData[position].isSelected = true
        notifyDataSetChanged()
    }

huangapple
  • 本文由 发表于 2020年10月6日 15:55:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/64221556.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定