wbk727
wbk727

Reputation: 8408

How to display a RadioButton list in PreferenceScreen (not in a Dialog)

How can a list of radio buttons be shown within a PreferenceSecreen rather than in a dialog? It's really annoying having to click more than once just to select an item from this list.

Expected result

enter image description here

Current result

enter image description here

enter image description here

app_preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <ListPreference
            android:key="prefPhotoFilter"
            android:title="Photo filter"
            android:entries="@array/photoFilters" />

</PreferenceScreen>

strings.xml

<string-array name="photoFilters">
    <item name="1">Natural</item>
    <item name="2">Boosted</item>
    <item name="3">Saturated</item>
</string-array>

enter image description here

Upvotes: 3

Views: 1431

Answers (1)

Abed
Abed

Reputation: 5217

According to this Gist, you can extend CheckBoxPreference and create a layout with a radio button.

Like this: First, create a new layout containing an only radio button let's call it

preference_widget_radiobutton.xml

<?xml version="1.0" encoding="utf-8"?>
<RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:clickable="false"
        android:focusable="false" />

then create a subclass of CheckBoxPreference:

class RadioButtonPreference : CheckBoxPreference {

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) { setView() }

    constructor(context: Context, attrs: AttributeSet? = null) : super(context, attrs) { setView() }


    private fun setView(){
        widgetLayoutResource = R.layout.preference_widget_radiobutton
    }

    override fun onClick() {
        if (this.isChecked) 
            return

        super.onClick()
    }
}

in your app_preferences.xml screen:

    <PreferenceCategory android:title="Photo Filters">
        <Your_class_package_dirctory.RadioButtonPreference
                android:key="naturals"
                android:title="Natural" />
        <Your_class_package_dirctory.RadioButtonPreference
                android:key="boosted"
                android:title="Boosted" />
        <Your_class_package_dirctory.RadioButtonPreference
                android:key="saturated"
                android:title="Saturated" />
    </PreferenceCategory>

Now as you can see this will behave like normal CheckBox, it won't get uncheck the previous radio button, to solve this issue:

In your preference screen code:


class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceClickListener{
    private val sharedPreference = AppPreferences()


    private var oldCheckedPreference: RadioButtonPreference? = null

    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.app_preferences, rootKey)

        findPreference<RadioButtonPreference>("naturals")?.apply {
            /*
            You can set the defualt button to be checked by:
              updateCheckedRadioButton(this)
            */
            onPreferenceClickListener = this@SettingsFragment
        }
        findPreference<RadioButtonPreference>("boosted")?.onPreferenceClickListener = this
        findPreference<RadioButtonPreference>("saturated")?.onPreferenceClickListener = this

    }

    private fun updateCheckedRadioButton(radioButtonPreference: RadioButtonPreference) {

        //Uncheck the previous selected button if there is.
        oldCheckedPreference?.isChecked = false
        radioButtonPreference.isChecked = true
        oldCheckedPreference = radioButtonPreference

    }

    override fun onPreferenceClick(preference: Preference): Boolean {
        if (preference is RadioButtonPreference)
            updateCheckedRadioButton(preference)

        return true
    }

}

and the result is:

result

Upvotes: 2

Related Questions