How to upgrade to AndroidX preferences?

225 Views Asked by At

I'm trying to upgrade to the new Androidx preference library. All tutorials I find involve creating masses of intertwined XML files, activities, and fragments, which makes everything much more complicated that it was before.

What I had before:

class PreferenceItem<T>(val key: String, val default: T){
    fun read(context: Context): T = PreferenceManager.getDefaultSharedPreferences(context).all.get(key) as T
}

enum class CoordRep { LATLNG, UTM }

class MyPreferences(context: Context){
    val coordSys = PreferenceItem("COORD_SYS", CoordRep.LATLNG)
    val showSmoothVideo = PreferenceItem("SHOW_SMOOTH_VIDEO", true)
}

class SettingsActivity : PreferenceActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        preferenceScreen = preferenceManager.createPreferenceScreen(this)
        val prefs = MyPreferences(this)

        preferenceScreen.addPreference(ListPreference(this).apply {
            key = prefs.coordSys.key
            value = prefs.coordSys.default.name
            entries = CoordRep.values().map { when(it){
                CoordRep.LATLNG ->"Lat/Long"; CoordRep.UTM ->"UTM"} }.toTypedArray()
            entryValues = CoordRep.values().map { it.name }.toTypedArray()
            title = "Coordinate Representation"
            summary = "Represent Coordinates as: %s"
        })

        preferenceScreen.addPreference(CheckBoxPreference(this).apply{
            key = prefs.showSmoothVideo.key
            setDefaultValue(prefs.showSmoothVideo.default)
            title = "Smooth Video"
            summary = "Enable smooth video"
        })

}

Question is - how can I upgrade this code to AndroidX? If I try, I first find that preferenceManager no longer exists because there is no PreferenceActivity for AndroidX.

And trying to do it with

val screen = PreferenceManager(this).createPreferenceScreen(this)

Gives me an error about PreferenceManager can only be called from within the same library group prefix

Is there a straightforward way to switch this over to the newer and supposedly superior AndroidX preference API?

1

There are 1 best solutions below

0
Peter On

Well, figured it out. Looks like you have to use a fragment.

class PreferenceItem<T>(val key: String, val default: T){
    fun read(context: Context): T = PreferenceManager.getDefaultSharedPreferences(context).all.get(key) as T
}

enum class CoordRep { LATLNG, UTM }

class MyPreferences(context: Context){
    val coordSys = PreferenceItem("COORD_SYS", CoordRep.LATLNG)
    val showSmoothVideo = PreferenceItem("SHOW_SMOOTH_VIDEO", true)
}

class SettingsActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.settings_activity)
        supportFragmentManager
            .beginTransaction()
            .replace(R.id.settings_container, SettingsFragment())
            .commit()
    }
}


class SettingsFragment: PreferenceFragmentCompat(){

    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        val context = preferenceManager.context
        preferenceScreen = preferenceManager.createPreferenceScreen(context)

        preferenceScreen.addPreference(ListPreference(context).apply {
            key = prefs.coordSys.key
            value = prefs.coordSys.default.name
            entries = CoordRep.values().map { when(it){
                CoordRep.LATLNG ->"Lat/Long"; CoordRep.UTM ->"UTM"} }.toTypedArray()
            entryValues = CoordRep.values().map { it.name }.toTypedArray()
            title = "Coordinate Representation"
            summary = "Represent Coordinates as: %s"
        })

        preferenceScreen.addPreference(CheckBoxPreference(context).apply{
            key = prefs.showSmoothVideo.key
            setDefaultValue(prefs.showSmoothVideo.default)
            title = "Smooth Video"
            summary = "Enable smooth video"
        })

It assume the existence of this silly XML file (which I would be more than happy to get rid of but don't want to waste any more time on this)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/settings_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

Not sure why this is an "improvement" over the old way but at least you won't have Android Studio complaining about deprecation anymore, and you get access to some new widgets like SeekBarPreference.