Элементы RadioButton, не сбрасываемые в RecyclerView

#android #android-recyclerview #notifyitemchanged

Вопрос:

Об этом уже спрашивали раньше, но эти решения мне не помогли. У меня есть RecyclerView, который можно прокручивать и только частично видеть на экране в любой момент времени. Он содержит список радиокнопок и некоторый текст, связанный с каждым элементом. Когда вы нажимаете на радиоприемник, последняя кнопка, выбранная до этого, должна отключиться. Это не так. Каждая кнопка, которую вы нажмете, будет выбрана, и другие, которые вы выбрали ранее, также останутся выбранными.

Все устроено так:

 <?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/white"
    tools:context=".ui.SettingsActivity">


<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="15dp"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="5dp"
        android:orientation="horizontal">

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/video_settings"
            android:textColor="@color/black"
            android:textStyle="bold"
            android:textSize="@dimen/clickableTextSize"
            android:layout_alignParentStart="true"
            />
</RelativeLayout>


<androidx.appcompat.widget.LinearLayoutCompat
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:weightSum="100"
        android:gravity="bottom"
        android:orientation="vertical">

    <TextView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="15"
            android:paddingStart="15dp"
            android:paddingEnd="15dp"
            android:text="@string/set_resolution_and_fps"
            android:textSize="@dimen/history_text_size"
            android:gravity="center_vertical"
            android:background="@color/grey_200"
            android:textColor="@color/black"
            />

<androidx.recyclerview.widget.RecyclerView
        android:id="@ id/rv_video_resolution"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="80"
        android:layout_marginTop="5dp"/>

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@ id/submitVideoSettings"
        android:text="@string/submit"
        android:layout_marginBottom="5dp"
        android:textColor="@color/black"
        android:layout_gravity="center|bottom"

        />

  </androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
 

Утилизатор выглядит так:

 <?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="3dp"
    android:orientation="horizontal"
    xmlns:android="http://schemas.android.com/apk/res/android">

<RadioButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@ id/resolutionRVRadioButton"
        />
<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@ id/resolutionRVTV"
        />

<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="5dp"
        android:text="@string/at_symbol"
        />

<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@ id/framesPerSecondRVTV"
        android:layout_marginStart="5dp"
        />

<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/fps"
        />
</androidx.appcompat.widget.LinearLayoutCompat>
 

Код адаптера выглядит следующим образом.

     class ResolutionRVAdapter(private val sharedNavAndMenuViewModel: SharedNavAndMenuViewModel,
                                private val lastResolutionSelected: String,
                                private val capabilityDataList: List<CameraCapabilitySpecificFPS>) : RecyclerView.Adapter<CameraResolutionRVAdapter.ViewHolder>(){
    private var lastCheckedPosition = -1

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CameraResolutionRVAdapter.ViewHolder {
        val v =  LayoutInflater.from(parent.context).inflate(R.layout.camera_resolution_recycler_item, parent, false)
        val viewHolder = ViewHolder(v)

        Timber.i("Added viewHolder: ${viewHolder.resolutionText.text}")

        return ViewHolder(v)
    }

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
        val resolutionRadioButton : RadioButton = itemView.findViewById(R.id.resolutionRVRadioButton)
        val resolutionText : TextView = itemView.findViewById(R.id.resolutionRVTV)
        val framesPerSecondText : TextView = itemView.findViewById(R.id.framesPerSecondRVTV)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val child = capabilityDataList[position]
        Timber.i("onBindViewHolder currently working with resolution ${child.resolution} range of $child.range")
        holder.resolutionText.text = child.resolution.toString()
        holder.framesPerSecondText.text = child.fps

        Timber.d("OnBindViewholder and lastResolutionSelected = $lastResolutionSelected")

        if(lastResolutionSelected.isEmpty()) {
            if(position == 0) {
                holder.resolutionRadioButton.isChecked = true
                Timber.i("No last resolution was selected. Setting index 0 to true")
            }
        } else if(lastResolutionSelected == holder.resolutionText.text.toString()) {
            Timber.i("An old resolution of ${holder.resolutionText.text} was selected. Setting index $position to true")
            holder.resolutionRadioButton.isChecked = true
        }

        holder.resolutionRadioButton.setOnClickListener {
            Timber.i("Index hit was: $position resolution at that index was: ${holder.resolutionText.text}")

            if(holder.resolutionRadioButton.isChecked) {
                //Button was already checked...must be the same button hit before...nothing to do
            } else {
                holder.resolutionRadioButton.isChecked = true
                runOnUiThread {
                    notifyItemChanged(lastCheckedPosition)
                    notifyItemChanged(position)
                }

                lastCheckedPosition = position
            }
        }
    }

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

Кто-нибудь может сказать мне, что я делаю не так?

Комментарии:

1. R adiobuttons не являются частью a radiogroup , поэтому вам нужно вручную снять флажки с других, когда один из них выбран, возможно, цикл в resolutionRadioButton.setOnClickListener снятой позиции в каждой позиции, кроме той, которая нажата, но состояние radiobuttons должно быть свойством child

2. В итоге я сделал это, но я не думаю, что это должно было быть сделано.