在recyclerview中,复选框状态在图形上不正确

时间:2018-08-27 08:57:03

标签: android android-recyclerview kotlin android-checkbox

我正在使用RecyclerView处理CheckBoxes的可选项目。我想通过以下规则实现可检查的项目:

  • 只能同时检查一个项目
  • 如果选中了该项目,则无法取消选中该项目(不能为零项目被选中)

每个项目都以编程方式启动时选中了一个复选框(默认为第一个)。原因很简单。 ArrayList中的每个项目都是自定义对象,其中的复选框状态表示为boolean,您可以保存状态并稍后再次打开它们。

因此,我将s etOnCheckedChangeListener()用于CheckBox,每次我遍历项Arraylist并将isChecked设置为true时, position等于tag中的位置。

这很好。我已经通过调试器检查了每个状态,并且状态正确,但是图形表示不正确,我也不知道为什么。

这是图形表示:

enter image description here

onBindViewHolder()代码:

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()
        }

    }

3 个答案:

答案 0 :(得分:0)

最简单的方法是将逻辑移到回收者视图之外。 (在清洁建筑的演示者中)

您有一个对象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)
}

您还必须防止(在视图持有者中)单击选中的项目。

答案 1 :(得分:0)

这是实现它的我的方式

  • 使复选框可聚焦,并将focusbleInTouchMode设置为false

  • 在适配器excheckedId中获取一个全局变量。

  • 在适配器onBindViewHolder中编写逻辑

    if(variantID==checkedId){

      holder.foodVariantCheckBox.isChecked=true
    

    }else{

    holder.foodVariantCheckBox.isChecked=false

    }

  • holder.foodVariantCheckBox设置OnclickListener。在onClick方法中,将checkedId设置为variantID和notifyDataSetChanged()

    最终选中的项目ID将在适配器的checkedId变量中。

答案 2 :(得分:0)

因此,我将@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()
    }