-->

Material Button Toggle Group single selection

2020-08-10 09:50发布

问题:

How can I force a MaterialButtonToggleGroup to act like a RadioGroup as in having at least one selected item always? Setting setSingleSelection(true) also adds the possibility to have nothing selected if you click twice on a Button in the group.

Here is my code:

<com.google.android.material.button.MaterialButtonToggleGroup
            android:id="@id/BottomSheetDialog_fromFragmentBottomSheetSort_Sort_ToggleButtonGroup"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:singleSelection="true"
            app:checkedButton="@+id/BottomSheetDialog_fromFragmentBottomSheetSort_Sort_ToggleButtonGroup_Ascending">

        <com.google.android.material.button.MaterialButton
                android:id="@id/BottomSheetDialog_fromFragmentBottomSheetSort_Sort_ToggleButtonGroup_Ascending"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/Fragment_BottomSheetDialog_Sort_ToggleButton_Ascending"
                app:backgroundTint="@color/custom_button_background_states"
                style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>

        <com.google.android.material.button.MaterialButton
                android:id="@id/BottomSheetDialog_fromFragmentBottomSheetSort_Sort_ToggleButtonGroup_Descending"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/Fragment_BottomSheetDialog_Sort_ToggleButton_Descending"
                app:backgroundTint="@color/custom_button_background_states"
                style="@style/Widget.MaterialComponents.Button.OutlinedButton"/>
    </com.google.android.material.button.MaterialButtonToggleGroup>

As you can see, even while using app:singleSelection="true" if i click on an already checked button, it unchecks it leaving no button checked in the group.

回答1:

Override the toggle() method of the MaterialButton class and use it instead of MaterialButton

import android.content.Context
import android.util.AttributeSet
import com.google.android.material.button.MaterialButton

class CustomMaterialToggleButton : MaterialButton {

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    override fun toggle() {
        if (!isChecked) {
            super.toggle()
        }
    }
}

This will make sure that already checked button is not unchecked on single selection.

UPDATE :

app:selectionRequired="true" attribute is available as of version 1.2.0



回答2:

As of 1.2.0-alpha03 you can simply use the selectionRequired option:

<com.google.android.material.button.MaterialButtonToggleGroup
    android:id="@+id/toggle_button_group"
    app:singleSelection="true"
    app:selectionRequired="true">

</com.google.android.material.button.MaterialButtonToggleGroup>


回答3:

Now you can achieve it using the app:selectionRequired attribute.
Something like:

    <com.google.android.material.button.MaterialButtonToggleGroup
        app:singleSelection="true"
        app:selectionRequired="true"
        app:checkedButton="@id/..."
        ..>

Also you can programmatically use the method setSelectionRequired:

buttonGroup.setSelectionRequired(true);

Please note that this attribute requires a minimum of version 1.2.0-alpha03



回答4:

If you really want to do this, you can go about it this way in Kotlin.

toggle_group.forEach { button ->
      button.setOnClickListener { (button as MaterialButton).isChecked = true }
}

This will prevent second click unchecking.