英文:
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<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();
// 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<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.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<CheckBox>(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()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论