Android preference fragment compat example

 The dependencies

implementation 'com.android.support:preference-v7:28.0.0-alpha3'
implementation 'com.android.support:preference-v14:28.0.0-alpha3'

The preference xml file that defines the setting ui. xml/pref_settings.xml, this will be used in the PreferenceFragmentCompat.

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

        <android.support.v7.preference.SwitchPreferenceCompat
            android:key="pref_allow_notification"
            android:title="Allow notification"
            android:defaultValue="false"
            android:icon="@drawable/ic_notifications_black_24dp"/>

        <android.support.v7.preference.EditTextPreference
            android:key="pref_key_zipcode"
            android:title="Zip code"
            android:hint="Enter a 5 digits zip code"
            android:inputType="text"
            android:singleLine="true"
            android:icon="@drawable/ic_edit_location_black_24dp"/>

    </PreferenceCategory>

    <PreferenceCategory
        android:title="Category Two">
        <android.support.v7.preference.ListPreference
            android:title="Unit"
            android:key="pref_key_unit"
            android:entryValues="@array/pref_unit_values"
            android:entries="@array/pref_unit_options"
            android:icon="@drawable/ic_edit_black_24dp"/>

        <android.support.v7.preference.Preference
            android:title="www.google.com"
            android:icon="@drawable/ic_web_black_24dp">
            <intent android:action="android.intent.action.VIEW"
                android:data="https://www.google.com/" />
        </android.support.v7.preference.Preference>

    </PreferenceCategory>

</PreferenceScreen>

SettingsFragment.kt, it extends from the PreferenceFragmentCompat. This is where the above preference xml is initialized, and binds the ui with the name pair value stored in shared preference, as well as listening to the preference changes and act accordingly.

import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.preference.ListPreference
import android.preference.PreferenceManager
import android.support.v7.preference.Preference
import android.support.v7.preference.PreferenceFragmentCompat
import android.view.View

class SettingsFragment: PreferenceFragmentCompat(), Preference.OnPreferenceChangeListener {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Hide the divider
        setDivider(ColorDrawable(Color.TRANSPARENT))
        setDividerHeight(0)
    }

    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.pref_settings)

        bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_key_zipcode)))
        bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_key_unit)))

    }

    private fun bindPreferenceSummaryToValue(preference: Preference) {
        preference.onPreferenceChangeListener = this

        onPreferenceChange(preference,
                PreferenceManager
                        .getDefaultSharedPreferences(preference.context)
                        .getString(preference.key, ""))
    }


    override fun onPreferenceChange(preference: Preference?, value: Any?): Boolean {
        val stringValue = value.toString()

        if (preference is ListPreference) {
            val listPreference = preference
            val prefIndex = listPreference.findIndexOfValue(stringValue)
            if (prefIndex >= 0) {
                preference.setSummary(listPreference.entries[prefIndex])
            }
        } else {
            preference?.summary = stringValue
        }
        return true
    }

    override fun onPreferenceTreeClick(preference: Preference): Boolean {
        return when (preference.key) {
            getString(R.string.pref_key_allow_notification) -> {
                true
            }
            getString(R.string.pref_key_zipcode) -> {
                true
            }
            getString(R.string.pref_key_unit) -> {
                true
            }
            else -> {
                super.onPreferenceTreeClick(preference)
            }
        }
    }

}

The SettingsActivity, which houses the above settings fragment.

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_settings.*

class SettingsActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_settings)
        setSupportActionBar(app_toolbar)

        supportActionBar?.setDisplayHomeAsUpEnabled(true)
        supportActionBar?.setDisplayShowHomeEnabled(true)

        supportFragmentManager.beginTransaction()
                .replace(R.id.content, SettingsFragment())
                .commit()
    }
}

The theme style for the SettingsActivity, it has to extend PreferenceThemeOverlay or the setting activity will crash.

<style name="AppTheme.PreferenceTheme" parent="AppTheme">
    <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>

Apply the above preference theme in the manifest file.

<activity
    android:name=".SettingsActivity"
    android:label="@string/action_settings"
    android:parentActivityName=".MainActivity"
    android:theme="@style/AppTheme.PreferenceTheme">
</activity>

The MainActivity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        setSupportActionBar(app_toolbar)
    }

    override fun onResume() {
        super.onResume()

        val sharedPref = PreferenceManager.getDefaultSharedPreferences(this)
        et_allow_notification.setText(sharedPref.getBoolean(getString(R.string.pref_key_allow_notification), false).toString())
        et_zipcode.setText(sharedPref.getString(getString(R.string.pref_key_zipcode), ""))
        et_unit.setText(sharedPref.getString(getString(R.string.pref_key_unit), ""))
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.menu_setting, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.

        return when (item.itemId) {
            R.id.action_settings -> {
                startActivity(Intent(this, SettingsActivity::class.java))
                true
            }
            else -> super.onOptionsItemSelected(item)
        }
    }
}

The layout file for the settings activity, activity_settings.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SettingsActivity">

    <android.support.v7.widget.Toolbar
        android:id="@+id/app_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:elevation="5dp"
        app:popupTheme="@style/Theme.AppCompat.Light.DarkActionBar"
        app:layout_constraintTop_toTopOf="parent">
    </android.support.v7.widget.Toolbar>

    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/app_toolbar"></FrameLayout>

</android.support.constraint.ConstraintLayout>

The layout file for the MainActivity, activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.support.v7.widget.Toolbar
        android:id="@+id/app_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:elevation="5dp"
        app:popupTheme="@style/Theme.AppCompat.Light.DarkActionBar"
        app:layout_constraintTop_toTopOf="parent">
    </android.support.v7.widget.Toolbar>


    <android.support.design.widget.TextInputLayout
        android:id="@+id/til_notification"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        app:layout_constraintTop_toBottomOf="@+id/app_toolbar">
        <android.support.design.widget.TextInputEditText
            android:id="@+id/et_allow_notification"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent"
            android:hint="Allow notification"
            android:enabled="false"
            tools:text="true"/>
    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/til_zipcode"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        app:layout_constraintTop_toBottomOf="@+id/til_notification">
        <android.support.design.widget.TextInputEditText
            android:id="@+id/et_zipcode"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent"
            android:hint="Zipcode"
            android:enabled="false"
            tools:text="10016"/>
    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/til_unit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        app:layout_constraintTop_toBottomOf="@+id/til_zipcode">
        <android.support.design.widget.TextInputEditText
            android:id="@+id/et_unit"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent"
            android:hint="Unit"
            android:enabled="false"
            tools:text="Fahrenheit"/>
    </android.support.design.widget.TextInputLayout>
</android.support.constraint.ConstraintLayout>

String resources, strings.xml

<resources>
    <string name="app_name">Android Preference Fragment</string>

    <string name="action_settings">Settings</string>
    <string name="appbar_scrolling_view_behavior" translatable="false">android.support.design.widget.AppBarLayout$ScrollingViewBehavior</string>

    <string name="pref_key_allow_notification" translatable="false">pref_allow_notification</string>
    <string name="pref_key_zipcode" translatable="false">pref_key_zipcode</string>
    <string name="pref_key_unit" translatable="false">pref_key_unit</string>

    <string-array name="pref_unit_options">
        <item>Celsius</item>
        <item>Fahrenheit</item>
    </string-array>

    <string-array name="pref_unit_values">
        <item>Celsius</item>
        <item>Fahrenheit</item>
    </string-array>

</resources>

menu/menu_setting.xml, this is the menu on the top right corner in the main screen.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.nerdery.testexample.ui.ScrollingActivity">
    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:title="@string/action_settings"
        app:showAsAction="never" />
</menu>

No comments:

Post a Comment

Note: only a member of this blog may post a comment.

How to extract filename from Uri?

Now, we can extract filename with and without extension :) You will convert your bitmap to uri and get the real path of your file. Now w...