I have the following xml that uses a radio button group to add radio buttons to it dynamically.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/list_item_sort_item"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RadioGroup
android:id="@+id/rbSortOptionGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Once the layout is inflated it looks something like this:
This is in a Dialog fragment and the user will select a radio button and click apply will close the dialog.
When the user opens the dialog fragment again the previous state of the radio button will be automatically selected. However, after selecting another radio button the saved radio button will remain checked so I always have 2 radio buttons selected at the sametime.
Is there a way to unselect this when selecting other radio buttons.
Here is my class when I dynamically create the radio buttons and add them to the radio group.
@EpoxyModelClass(layout = R.layout.list_item_sort_item)
abstract class SortItemModel(private val schedulersFacade: SchedulersFacade) : EpoxyBaseModel() {
@EpoxyAttribute
lateinit var listOfTopsProductSort: List<TopsProductSort>
@EpoxyAttribute
lateinit var tapSortButtonRelay: PublishRelay<TopsProductSort>
override fun bind(holder: EpoxyBaseViewHolder) {
with(holder.itemView) {
rbSortOptionGroup.removeAllViews()
listOfTopsProductSort.forEach { topsProductSort ->
val materialRadioButton = MaterialRadioButton(context)
materialRadioButton.setTextColor(ColorStateList.valueOf(ContextCompat.getColor(context, R.color.black)))
materialRadioButton.text = topsProductSort.name
materialRadioButton.tag = TopsProductSort(code = topsProductSort.code, name = topsProductSort.name)
materialRadioButton.isChecked = topsProductSort.isSelected // Set the previous radio button that was selected
materialRadioButton.clicks()
.debounce(250L, TimeUnit.MILLISECONDS)
.observeOn(schedulersFacade.ui)
.map {
materialRadioButton.tag as TopsProductSort
}
.subscribeBy(
onNext = { _topsProductSort ->
if (materialRadioButton.tag is TopsProductSort) {
tapSortButtonRelay.accept(_topsProductSort.copy(isSelected = true))
}
},
onError = {
Timber.e(it.localizedMessage)
}
)
rbSortOptionGroup.addView(materialRadioButton)
}
}
}
To avoid this behaviour when creating a MaterialRadioButton
programmatically you need to set a Unique Identifier @+id
for each MaterialRadioButton
so that RadioGroup
can identify each of its children during of its selection/unselection phase. For this purpose you can use the ViewCompat.generateViewId()
to generate a Unique Id programmatically.
During the creation of each MaterialRadioButton
you can use the above method like below:
val materialRadioButton = MaterialRadioButton(context)
materialRadioButton.id = ViewCompat.generateViewId()
By doing the above the RadioGroup
will be able to uniquely identify each of its children and will act as a Single selection.