Settings with PreferenceFragment - TechGeekD/android_guides GitHub Wiki

Overview

In Android apps, there are often settings pages that contain different options the user can tweak. The PreferenceFragment contains a hierarchy of preference objects displayed on screen in a list. These preferences will automatically save to SharedPreferences as the user interacts with them.

PreferenceFragment requires a minimum API level of 11. To support older versions, there is the PreferenceActivity. However, after API level 11, many methods associated with the PreferenceActivity became deprecated. The suggested way of handling settings is through the PreferenceFragment.

Defining the XML

First, define the preference object hierarchy by creating a new xml file in res/xml:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
   
    <PreferenceCategory
        android:title="@string/title_first_section">
 
        <CheckBoxPreference
            android:key="checkbox_preference"
            android:title="@string/title_checkbox_preference"
            android:defaultValue="@string/default_checkbox_preference"/>
            
        <EditTextPreference
            android:key="edittext_preference"
            android:title="@string/title_edittext_preference"
            android:summary="@string/summary_edittext_preference"
            android:dialogTitle="@string/dialog_title_edittext_preference"
            android:dependency="checkbox_preference" />
 
        </PreferenceCategory>
 
    <PreferenceCategory
        android:title="@string/title_second_section">
 
        <ListPreference
            android:key="list_preference"
            android:title="@string/title_list_preference"
            android:dialogTitle="@string/dialog_title_list_preference"
            android:entries="@array/entries_list_preference"
            android:entryValues="@array/entryvalues_list_preference" />
 
        <Preference
            android:title="@string/title_intent_preference">
            <intent android:action="android.intent.action.VIEW"
                android:data="http://codepath.com/" />
        </Preference>
 
        </PreferenceCategory>
 
</PreferenceScreen>

All preferences are saved as key-value pairs in the default SharedPreferences with the key specified through the xml above. To retrieve an instance of those preferences, call the following with a context in the same package as the fragment:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(android.content.Context);

The root for the XML file must be a <PreferenceScreen>. Within this screen, you can either list all preferences or group with <PreferenceCategory>. The grouped preferences will appear together under the same section heading. The XML above creates the following setting screen:

![Settings Screen](https://i.imgur.com/qkE1W6H.png?1 =200x)

Preference Types

There are several main types of preferences used for settings:

  • ListPreference: opens dialog with a list of options (see below for defining options); persists a string
  • EditTextPreference: opens a dialog with an EditText view for typed input; persists a string
  • CheckBoxPreference: uses a checkbox to persist a boolean (true when checked, false when unchecked)
  • SwitchPreference (min API 14): uses a switch to persist a boolean (true when on, false when off)

Two of these preference types (ListPreference and EditTextPreference) descend from DialogPreference and can therefore define dialog-specific attributes in the XML (e.g. a dialogTitle).

Note that the SwitchPreference type was introduced in API 14 as a subclass of TwoStatePreference. At this time,CheckBoxPreference was also implemented to also be a direct subclass of it rather directly fromPreference. To use SwitchPreference, your app needs to use either min API level 14 or the Android support v4 library.

Defining the ListPreference Options

Two arrays must be specified when defining a list array. The first is under android:entries, which specifies human-readable options to display to the user. Second is an array of the values for each corresponding option, which is defined by android:entryValues.

    <ListPreference
        android:key="list_preference"
        android:title="@string/title_list_preference"
        android:dialogTitle="@string/dialog_title_list_preference"
        android:entries="@array/entries_list_preference"
        android:entryValues="@array/entryvalues_list_preference" />

Intents in Preferences

Preferences can also hold intents which can open a new activity or perform other intent actions. No data is persisted.

    <Preference
        android:title="@string/title_intent_preference">
        <intent android:action="android.intent.action.VIEW"
            android:data="http://codepath.com/" />
    </Preference>

Java Implementation

Use PreferenceFragment to programatically handle preferences. To load the settings into the fragment, load the preferences in the onCreate() method. To get an instance of a preference, search for a preference using its key through the PreferenceManager within onCreateView(). You can use this instance to customize the preference, such as add a custom OnPreferenceChangeListener.

public class SettingsFragment extends PreferenceFragment {
    
    private ListPreference mListPreference;
    
    ...
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.settings);
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        
        mListPreference = (ListPreference)  getPreferenceManager().findPreference("preference_key");
        mListPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                // insert custom code
            }
        }
        
        return inflater.inflate(R.layout.fragment_settings, container, false);
    }
}

Currently, Android support v4 does not support PreferenceFragment. For alternatives, there are several open-source projects available:

You can also follow this issue on the Android issue tracker.

Custom Preferences

If none of the previous preference types work for your needs, you can create a custom preference extending from DialogPreference, TwoStatePreference, or Preference itself.

For a detailed guide on implementing a custom preference, refer to the Android Developer: Settings API guide.

References