Состояния флажков графически некорректны в окне просмотра - PullRequest
0 голосов
/ 27 августа 2018

Я работаю над RecyclerView с выбираемыми элементами, используя CheckBoxes.Я хочу получить проверяемые элементы по следующим правилам:

  • Только ОДИН элемент может быть проверен одновременно
  • Если элемент отмечен, этот элемент не может быть проверенснят (с отметки не может быть ноль проверенных элементов)

Каждый элемент имеет один выбранный флажок при запуске программно (по умолчанию это первый).Причина этого проста.Каждый элемент в ArrayList - это пользовательский объект, чье состояние флажка представлено как логическое значение внутри, и вы сможете сохранять состояния и открывать их позже.

Поэтому я использовал s etOnCheckedChangeListener() для своего CheckBox и каждый разЯ переберу Arraylist элементов и установлю isChecked на true, только если его позиция равна позиции в 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 голосов
/ 27 августа 2018

Вот мой способ его реализации

  • Сделать флажок focusable и focusbleInTouchMode равным false

  • Взять глобальную переменную в адаптере ex checkedId.

  • В адаптере onBindViewHolder написать логику

    if(variantID==checkedId){

      holder.foodVariantCheckBox.isChecked=true
    

    }else{

    holder.foodVariantCheckBox.isChecked=false

    }

  • Установите OnclickListener для holder.foodVariantCheckBox.В методе onClick введите checkId для variableID и notifyDataSetChanged()

    Окончательный идентификатор проверяемого элемента будет находиться в переменной adapterId адаптера.

0 голосов
/ 27 августа 2018

Итак, я объединил ответы @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()
    }
0 голосов
/ 27 августа 2018

Самый простой способ сделать это - переместить логику за пределы представления переработчика.(В презентере в чистой архитектуре)

У вас есть список объектов 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)
}

Вы также должны запретить (в окне просмотра) снятие отметки с отмеченного элемента при нажатии на него.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...