Android recyclerview中的复选框状态在图形上不正确
我正在使用Android recyclerview中的复选框状态在图形上不正确,android,android-recyclerview,kotlin,android-checkbox,Android,Android Recyclerview,Kotlin,Android Checkbox,我正在使用复选框使用可选项处理回收视图。我希望使用以下规则实现可检查项: 同时只能检查一个项目 如果选中项目,则无法取消选中该项目(选中的项目不能为零) 每个项目在开始时都有一个以编程方式选中的复选框(默认为第一个)。原因很简单。ArrayList中的每个项都是自定义对象,其中的复选框状态表示为布尔值,您可以保存状态并稍后再次打开它们 因此,我对我的复选框使用了setOnCheckedChangeListener(),每次我都会遍历项目的Arraylist,并将isChecked设置为tru
复选框
使用可选项处理回收视图
。我希望使用以下规则实现可检查项:
- 同时只能检查一个项目
- 如果选中项目,则无法取消选中该项目(选中的项目不能为零)
复选框使用了setOnCheckedChangeListener()
,每次我都会遍历项目的Arraylist
,并将isChecked
设置为true
,前提是它的位置等于标记中的位置
这很有效。我已经通过调试器检查了每个状态,状态是正确的,但图形表示不正确,我不知道为什么
这是图形表示:
onBindViewHolder()
code:
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int){
try {
if (holder is ViewHolder){
val res = holder.itemView.context.resources
val ctx = holder.itemView.context
foodVariants[position].let{
//food variant vals
val variantID: Int = it.foodVariant.getInt(ctx.getString(R.string.food_variant_id))
val variantName: String? = it.foodVariant.getString(ctx.getString(R.string.food_variant_name))
val variantPrice: Int = it.foodVariant.getInt(ctx.getString(R.string.food_variant_price))
//set food variant name
holder.foodVariantName.text = variantName
//set food variant price
val variantPriceConverted: String = convertCentsToFloat(variantPrice)
holder.foodVariantPrice.text = variantPriceConverted + " €"
//set item tag
holder.foodVariantCheckBox.tag = position
//set food variant state
holder.foodVariantCheckBox.isChecked = it.isChecked
//uncheck all variants if this is checked - one variant has to be checked everytime
holder.foodVariantCheckBox.setOnCheckedChangeListener { buttonView, isChecked ->
val newPosition = buttonView.tag as Int
createLog("VARIANT_STATE: ", "isChecked: " + variantName.toString())
for (variantPos in 0 until foodVariants.size){
foodVariants[variantPos].isChecked = variantPos == newPosition
}
mActivity.refreshOtherRecyclerViews(it)
notifyDataSetChanged()
}
}
}
} catch (e: Exception){
e.printStackTrace()
}
}
最简单的方法是将逻辑移到recycler视图之外。(在clean architecture中的演示者中)
您有一个对象列表CheckboxModel(val-id:Int,val-label:String,var-isChecked:Boolean)
。单击复选框时,更新CheckboxModel列表并将其传递回适配器:
fun onUpdate(selectedCase: CheckboxModel) {
data.forEach { it.isChecked = it.id == selectedCase.id }
updateAdapter(data)
}
您还必须防止(在视图持有者中)在单击选中的项目时取消选中该项目。以下是我的实现方法
- 将复选框设置为可聚焦,将focusbleInTouchMode设置为false
- 在适配器ex checkedId中获取一个全局变量
- 在adapter
onBindViewHolder
中编写一个逻辑
if(variantID==checkedd){
}其他{
holder.foodVariantCheckBox.isChecked=false
}
- 为holder.foodVariantCheckBox设置OnclickListener
。在onClick方法中,将checkedId设置为variantID并notifyDataSetChanged()
最终选中的项目id将位于适配器checkedId变量中
所以我把@Redman和@Kélian的答案结合起来,让它起作用
这是最终代码:
private var previouslySelectedVariant: Int = -1
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int){
try {
if (holder is ViewHolder){
val res = holder.itemView.context.resources
val ctx = holder.itemView.context
foodVariants[position].let{
//food variant vals
val variantID: Int = it.foodVariant.getInt(ctx.getString(R.string.food_variant_id))
val variantName: String? = it.foodVariant.getString(ctx.getString(R.string.food_variant_name))
val variantPrice: Int = it.foodVariant.getInt(ctx.getString(R.string.food_variant_price))
//set food variant name
holder.foodVariantName.text = variantName
//set food variant price
val variantPriceConverted: String = convertCentsToFloat(variantPrice)
holder.foodVariantPrice.text = variantPriceConverted + " €"
//set food variant state
holder.foodVariantCheckBox.isChecked = it.isChecked
//uncheck all variants if this is checked - one variant has to be checked everytime
holder.foodVariantCheckBox.setOnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
mActivity.updateVariantData(variantID)
mActivity.refreshIngredients(it)
previouslySelectedVariant = variantID
} else {
if(previouslySelectedVariant == variantID){
holder.foodVariantCheckBox.isChecked = true
}
}
}
}
}
} catch (e: Exception){
e.printStackTrace()
}
}
//ParentActivity
fun updateVariantData(variantID: Int){
foodVariantsArray.forEach { it.isChecked = it.foodVariant.getInt(getString(R.string.food_variant_id)) == variantID }
foodVariantsAdapter.notifyDataSetChanged()
}
小部件是一个复选框还是一个单选按钮?这与上面显示的问题相同。如果从上到下单击项目,则仅选中一个项目,但如果单击上一个项目,则两个项目都将选中。
private var previouslySelectedVariant: Int = -1
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int){
try {
if (holder is ViewHolder){
val res = holder.itemView.context.resources
val ctx = holder.itemView.context
foodVariants[position].let{
//food variant vals
val variantID: Int = it.foodVariant.getInt(ctx.getString(R.string.food_variant_id))
val variantName: String? = it.foodVariant.getString(ctx.getString(R.string.food_variant_name))
val variantPrice: Int = it.foodVariant.getInt(ctx.getString(R.string.food_variant_price))
//set food variant name
holder.foodVariantName.text = variantName
//set food variant price
val variantPriceConverted: String = convertCentsToFloat(variantPrice)
holder.foodVariantPrice.text = variantPriceConverted + " €"
//set food variant state
holder.foodVariantCheckBox.isChecked = it.isChecked
//uncheck all variants if this is checked - one variant has to be checked everytime
holder.foodVariantCheckBox.setOnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
mActivity.updateVariantData(variantID)
mActivity.refreshIngredients(it)
previouslySelectedVariant = variantID
} else {
if(previouslySelectedVariant == variantID){
holder.foodVariantCheckBox.isChecked = true
}
}
}
}
}
} catch (e: Exception){
e.printStackTrace()
}
}
//ParentActivity
fun updateVariantData(variantID: Int){
foodVariantsArray.forEach { it.isChecked = it.foodVariant.getInt(getString(R.string.food_variant_id)) == variantID }
foodVariantsAdapter.notifyDataSetChanged()
}