PreferenceFragmentCompat vs PreferenceFragment
PreferenceFragmentCompat v7
is supported on API Level 7 while PreferenceFragment
require API level 11.
PreferenceFragmentCompat
have additional features like setDivider
Based on PreferenceFragment documentation, PreferenceFragment class was deprecated in API level P. Use PreferenceFragmentCompat.
If you are interested to implement PreferenceFragment
, refer to Create Settings Preference Activity In Android Using PreferenceFragment.
Implementation
Import library
Include the com.android.support:preference
in modules's build.gradle
.
// implementation 'com.android.support:preference-v7:26.1.0'
// compile 'com.android.support:preference-v14:26.1.0'
// https://developer.android.com/topic/libraries/support-library/revisions.html
implementation 'com.android.support:preference-v14:26.1.0'
NOTE: There are 2 version of Preference Support Library: v7 and v14
NOTE: You can check for Recent Support Library Revisions
PreferenceFragmentCompat sample code
NOTE: make sure you use all android.support.v7.preference.*
classes and don't mix with android.preference.*
.
NOTE: PreferenceFragment.onCreate(savedInstanceState: Bundle?)
-> PreferenceFragmentCompat.onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?)
import android.support.v7.app.AppCompatActivityimport android.support.v7.preference.EditTextPreferenceimport android.support.v7.preference.Preferenceimport android.support.v7.preference.PreferenceFragmentCompatimport android.support.v7.preference.SwitchPreferenceCompatclass SettingsActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_settings) setSupportActionBar(toolbar) // android.R.id.content is probably for old style activity supportFragmentManager.beginTransaction() // .replace(android.R.id.content, SettingsFragment()) .replace(R.id.content, SettingsFragment()) .commit() } class SettingsFragment: PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { // Load the preferences from an XML resource addPreferencesFromResource(R.xml.pref_settings) } }}
Content of R.layout.activity_settings
.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.SettingsActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<!-- android:id="@android:id/content" -->
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"></FrameLayout>
</android.support.constraint.ConstraintLayout>
</android.support.design.widget.CoordinatorLayout>
Content of R.xml.pref_settings
.
NOTE: there is no need to use android.support.v7.preference.Preference
in xml.
NOTE: android.support.v7.preference.Preference
is required if you plan to override the class to create a custom Preference
.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Login"
android:key="pref_key_login_settings">
<Preference
android:key="@string/pref_key_change_password"
android:title="Change Password"
/>
<EditTextPreference
android:key="@string/pref_key_change_password_hint"
android:title="Change Password Hint"
/>
</PreferenceCategory>
<PreferenceCategory
android:title="Security"
android:key="pref_key_security_settings">
<SwitchPreference
android:key="@string/pref_key_auto_lock"
android:title="Auto Lock"
android:summary="Always prompt password login when the app is inactive for a while"
/>
</PreferenceCategory>
<PreferenceCategory
android:title="About"
android:key="pref_key_about_settings">
<Preference
android:key="@string/pref_key_upgrade"
android:title="Upgrade"
android:summary="Pro for peace of mind or be a Patron to support our work"
/>
<Preference
android:key="@string/pref_key_rate"
android:title="❤ LuaPass"
android:summary="Rate LuaPass on Play Store"
/>
<Preference
android:key="@string/pref_key_contact"
android:title="Feedback"
android:summary="Email us for question, suggestion or bug report"
/>
<Preference
android:key="@string/pref_key_version"
android:title="Version"
/>
</PreferenceCategory>
</PreferenceScreen>
Edit preferenceTheme
Edit res/values/styles.xml
to include preferenceTheme
.
<style name="AppTheme.NoActionBar">
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
<!-- <item name="preferenceTheme">@style/PreferenceThemeOverlay</item> -->
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
NOTE: you will bump into java.lang.IllegalStateException: Must specify preferenceTheme in theme
exception if preferenceTheme
is not set
Make sure the activity apply this theme is AndroidManifest.xml
.
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<application ...>
...
<activity
android:name=".view.SettingsActivity"
android:label="@string/title_activity_settings"
android:parentActivityName=".MainActivity"
android:theme="@style/AppTheme.NoActionBar"
>
</activity>
</application>
</manifest>
Start activity on preference click
class SettingsFragment: PreferenceFragmentCompat() { ... override fun onPreferenceTreeClick(preference: Preference): Boolean { return when (preference.key) { getString(R.string.pref_key_change_password) -> { startActivity(Intent(activity, ChangePasswordActivity::class.java)) true } else -> { super.onPreferenceTreeClick(preference) } } }}
Disable SwitchPreference change state but still listen to click
class SettingsFragment: PreferenceFragmentCompat() { ... override fun onPreferenceTreeClick(preference: Preference): Boolean { return when (preference.key) { getString(R.string.pref_key_auto_lock) -> { (preference as SwitchPreferenceCompat).isChecked = false AlertDialog.Builder(activity) .setTitle("Coming Soon") .setMessage("This feature shall be available in coming releases.") .setPositiveButton("Support Us") { dialog, whichButton -> } .setNegativeButton(android.R.string.cancel, null) .show() true } else -> { super.onPreferenceTreeClick(preference) } } }}
Hide divider of PreferenceFragmentCompat
class SettingsFragment: PreferenceFragmentCompat() { ... override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) setDivider(null) }}
NOTE: the above code can be put in onViewCreated
as well