I'm using a PreferenceActivity in my app. Defined the settings.xml as follows -
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="Preferences" >
<PreferenceCategory android:title="Email Options" >
<EditTextPreference
android:dialogTitle="#string/pref_email_user_title"
android:key="pref_email_user"
android:summary="#string/pref_email_user_summary"
android:persistent="true"
android:title="#string/pref_email_user_title" />
<EditTextPreference
android:dialogTitle="#string/pref_email_password_title"
android:key="pref_email_password"
android:summary="#string/pref_email_password_summary"
android:persistent="true"
android:title="#string/pref_email_password_title" />
</PreferenceCategory>
Activity as follows -
public class Prefs extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
}
}
Which is all you need, right? Apparently not though, because what happens is that I click on the 'email user' setting, it brings up a dialog which I use to type in a string value. However what I typed in isn't getting placed on the Settings screen, I still see the default value.
I notice that the values are getting persisted in the preferences file under /data/data/<package>/shared_prefs
I also don't see these persisted values when I relaunch the app - it shows default values. What's the bit of magic I'm missing?
You need an OnPreferenceChangeListener that will listen for changes on your preferences and automatically update the preference summary.
See this code from the samples in the SDK:
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(
index >= 0
? listPreference.getEntries()[index]
: null);
} else if (preference instanceof RingtonePreference) {
// For ringtone preferences, look up the correct display value
// using RingtoneManager.
if (TextUtils.isEmpty(stringValue)) {
// Empty values correspond to 'silent' (no ringtone).
preference.setSummary(R.string.pref_ringtone_silent);
} else {
Ringtone ringtone = RingtoneManager.getRingtone(
preference.getContext(), Uri.parse(stringValue));
if (ringtone == null) {
// Clear the summary if there was a lookup error.
preference.setSummary(null);
} else {
// Set the summary to reflect the new ringtone display
// name.
String name = ringtone.getTitle(preference.getContext());
preference.setSummary(name);
}
}
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
return true;
}
};
You need to bind this to all your preference items, for example like this:
bindPreferenceSummaryToValue(findPreference("username"));
And:
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* #see #sBindPreferenceSummaryToValueListener
*/
private static void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
Related
Okay so I'm trying to make sense of how Shared Preference works with Preference.
Below is part of an app that works, but I do not understand how it works for the part of Shared Preference.
I have a UserPrefActivity.java containing the following code
public class UserPrefActivity extends PreferenceActivity {
//a preference value change listener that updates the preference summary
//to reflect its new value
private static Preference.OnPreferenceChangeListener
sBindPreferenceSummaryToValueListerner = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
//gets string value of object
String value = newValue.toString();
Log.e("in sBind Listener", value);
//if the preference is a list preference, get the value at a given index
if (preference instanceof ListPreference) {
//for list preference look up the correct display value
//in the preference entries array
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(value);
//set the summary to reflect the new value
preference.setSummary(index >= 0 ? listPreference.getEntries()[index] : null);
} else {
//set summary to only value
preference.setSummary(value);
}
return true;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//call the deprecated method to load the preference screen
addPreferencesFromResource(R.xml.user_pref);
//get default Shared preference from preference screen
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
Preference saveNumPizza = findPreference("saveNumPizza");
//set the preference change listener to saveNumPizza
saveNumPizza.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListerner);
sBindPreferenceSummaryToValueListerner.onPreferenceChange(saveNumPizza,
PreferenceManager
.getDefaultSharedPreferences(this)
.getString(saveNumPizza.getKey(), ""));
}
}
In the MainActivity.java, I have the following as part of a bigger piece of code
//gets the default shared preference instance and assign to sharedPrefs for enabled save
// data
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences
(MainActivity.this);
//checks if save order status is true
if (sharedPrefs.getBoolean("saveOrder", false)) {
//do stuff..
}
I have the following UserPref.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:defaultValue="false"
android:key="saveOrder"
android:summary="for quick loading of favourite order"
android:title="Enable Saving Order"/>
<PreferenceCategory android:title="ORDER HISTORY">
<CheckBoxPreference
android:defaultValue="false"
android:key="keepHistory"
android:summary="of pizza orders"
android:title="Keep History"/>
<ListPreference
android:defaultValue="3"
android:dialogTitle="Choose how many to save"
android:entries="#array/number_of_pizza"
android:entryValues="#array/number_of_pizza_values"
android:summary="3 pizza orders"
android:key="saveNumPizza"
android:title="Number of Orders"/>
</PreferenceCategory>
</PreferenceScreen>
I know that in the UserPrefsActivity, I believe in the PreferenceManager.getDefaultSharedPreferences(this) call, the shared preferences is created and obtained if it does not exist, if it does its just obtained.
From what I've noticed with the app, is that on first launch when I get to the settings and launch the UserPrefActivity via intent, the shared preference of the UserPrefActivity is created, containing only the saveNumPizza key. However the minute I click on the other preferences (Checkbox preference) when I look at the shared preference file, I immediately see that the saveOrder key and keepHistory key are automatically saved.
I would just like to know how this automatic saving is exactly done since I am not using an editor to save it to the shared preference, nor am I calling apply or commit.
Thank you,
I want to give the user the option of choosing between several different colour themes in my app in the settings activity. I know how to bundle/save/load the prefs, nevertheless I'm having trouble accomplishing this.
I have defined my colors in colors.xml, defined several themes in v21styles.xml, and added the options to a listview in the SettingsActivity.java.
The only part I am having difficulty with is actually applying the new themes. I would like to set up a switch statement to apply the themes using the built in android methods, but am not exactly how to accomplish this on API 21 (lolipop).
public class SettingsActivity extends PreferenceActivity {
/**
* Determines whether to always show the simplified settings UI, where
* settings are presented in a single list. When false, settings are shown
* as a master/detail two-pane view on tablets. When true, a single pane is
* shown on tablets.
*/
private static final boolean ALWAYS_SIMPLE_PREFS = false;
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
setupSimplePreferencesScreen();
}
/**
* Shows the simplified settings UI if the device configuration if the
* device configuration dictates that a simplified, single-pane UI should be
* shown.
*/
private void setupSimplePreferencesScreen() {
if (!isSimplePreferences(this)) {
return;
}
// In the simplified UI, fragments are not used at all and we instead
// use the older PreferenceActivity APIs.
// Add 'general' preferences.
addPreferencesFromResource(R.xml.pref_general);
}
/**
* {#inheritDoc}
*/
#Override
public boolean onIsMultiPane() {
return isXLargeTablet(this) && !isSimplePreferences(this);
}
/**
* Helper method to determine if the device has an extra-large screen. For
* example, 10" tablets are extra-large.
*/
private static boolean isXLargeTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
/**
* Determines whether the simplified settings UI should be shown. This is
* true if this is forced via {#link #ALWAYS_SIMPLE_PREFS}, or the device
* doesn't have newer APIs like {#link PreferenceFragment}, or the device
* doesn't have an extra-large screen. In these cases, a single-pane
* "simplified" settings UI should be shown.
*/
private static boolean isSimplePreferences(Context context) {
return ALWAYS_SIMPLE_PREFS
|| Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB
|| !isXLargeTablet(context);
}
/**
* {#inheritDoc}
*/
#Override
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
if (!isSimplePreferences(this)) {
loadHeadersFromResource(R.xml.pref_headers, target);
}
}
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(
index >= 0
? listPreference.getEntries()[index]
: null);
} else if (preference instanceof RingtonePreference) {
// For ringtone preferences, look up the correct display value
// using RingtoneManager.
if (TextUtils.isEmpty(stringValue)) {
// Empty values correspond to 'silent' (no ringtone).
preference.setSummary(R.string.pref_ringtone_silent);
} else {
Ringtone ringtone = RingtoneManager.getRingtone(
preference.getContext(), Uri.parse(stringValue));
if (ringtone == null) {
// Clear the summary if there was a lookup error.
preference.setSummary(null);
} else {
// Set the summary to reflect the new ringtone display
// name.
String name = ringtone.getTitle(preference.getContext());
preference.setSummary(name);
}
}
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
return true;
}
};
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* #see #sBindPreferenceSummaryToValueListener
*/
private static void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
/**
* This fragment shows general preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GeneralPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("example_text"));
bindPreferenceSummaryToValue(findPreference("example_list"));
}
}
/**
* This fragment shows notification preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class NotificationPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_notification);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
}
}
/**
* This fragment shows data and sync preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class DataSyncPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_data_sync);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("sync_frequency"));
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// 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.
switch (item.getItemId()) {
case R.string.theme:
//apply red theme
R.style.RedTheme;
break;
case R.style.IndigoTheme:
//apply blue theme
case R.style.AppTheme:
//apply default theme
return true;
}
return super.onOptionsItemSelected(item);
}}
The part at the bottom is where I am trying to do the actual theme swapping. Is this the correct way to handle preference options even though it's technically not a "menu item"?
I have defined the theme names in my styles.xml, and v21/styles.xml. In the manifest the theme is set to AppTheme. I just want to be able to swap themes when the user selects a new theme in the preferences activity.
I think you have to do this with following in your switch case:-
themeUtils.changeToTheme(this, themeUtils.ur_theme_name);
Take a look into this following tutorial http://www.developer.com/ws/android/changing-your-android-apps-theme-dynamically.html..Hope it will helps you.
It gives me the error "findPreference(java.lang.CharSequence) is deprecated" .Currently, I am targeting API 10 and above for my application. Any kind of help to resolve this will be appreciated.
public class SettingsActivity extends PreferenceActivity
implements Preference.OnPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add 'general' preferences, defined in the XML file
// TODO: Add preferences from XML
addPreferencesFromResource(R.xml.pref_general);
bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key));
// For all preferences, attach an OnPreferenceChangeListener so the UI summary can be
// updated when the preference changes.
// TODO: Add preferences
}
/**
* Attaches a listener so the summary is always updated with the preference value.
* Also fires the listener once, to initialize the summary (so it shows up before the value
* is changed.)
*/
private void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(this);
// Trigger the listener immediately with the preference's
// current value.
onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list (since they have separate labels/values).
ListPreference listPreference = (ListPreference) preference;
int prefIndex = listPreference.findIndexOfValue(stringValue);
if (prefIndex >= 0) {
preference.setSummary(listPreference.getEntries()[prefIndex]);
}
} else {
// For other preferences, set the summary to the value's simple string representation.
preference.setSummary(stringValue);
}
return true;
}
}
It is deprecated because Android moved to fragment-based activities. Calling findPreference(CharSequence) will still work in higher API levels. You are just encouraged to use fragments instead of a PreferenceActivity.
The reason for the deprecation can be found in the source:
This function is not relevant for a modern fragment-based PreferenceActivity.
In API 11+ you should use PreferenceFragment.
If you want to have your IDE ignore the error just add the following to your method: #SuppressWarnings("deprecation")
public class SettingsActivity extends PreferenceActivity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add 'general' preferences, defined in the XML file
getFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();
// For all preferences, attach an OnPreferenceChangeListener so the UI summary can be
// updated when the preference changes.
}
public static class MyPreferenceFragment extends PreferenceFragment implements Preference.OnPreferenceChangeListener {
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_details);
bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key)));
}
private void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(this);
// Trigger the listener immediately with the preference's
// current value.
onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list (since they have separate labels/values).
ListPreference listPreference = (ListPreference) preference;
int prefIndex = listPreference.findIndexOfValue(stringValue);
if (prefIndex >= 0) {
preference.setSummary(listPreference.getEntries()[prefIndex]);
}
} else {
// For other preferences, set the summary to the value's simple string representation.
preference.setSummary(stringValue);
Log.v("onpreferencechange",stringValue);
}
return true;
}
}
Instead of adding the methods
bindPreferenceSummaryToValue(Preference preference) &
onPreferenceChange(Preference preference, Object value)
inside the main SettingsActivity class create a fragment class which implements the Preference.OnPreferenceChangeListener add the both the methods inside it.
check out the code provided
hope it helps
Well here is the solution:
API Level 11+ introduced PreferenceFragment as another way of
constructing the contents of a PreferenceActivity. You are welcome to
use them, but if you are still supporting older devices, you cannot
use PreferenceFragment for those devices.
Try the following link:
Non Deprecated findPreference() Method? - Android
I am new to android and I would appreciate your help. This is my first question =D Sorry for giving only two links and no images, I have not enought reputation to made my question more clear
Acording to android API guides for settings, I am using PreferenceFragment because I am developing for Android 3.0 (API level 11) and higher.
I want to achieve a effect as shown at figure 4 and 5 from android API guides for settings link.
On tablet emulator it looks ok, but on handset emulator (and real device) I can not achieve it. Instead I get "Sound", "Display", "Storage", "Battery"... as PreferenceCategory (like "Device" seems) followed by all the options that should be in a new screen (activity). All in only one screen.
Here are my files, thanks in advance
Settings.java (NOTE: Autogenerated and completed by myself)
package com.example;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.RingtonePreference;
import android.text.TextUtils;
import java.util.List;
import java.util.concurrent.FutureTask;
/**
* A {#link PreferenceActivity} that presents a set of application settings. On
* handset devices, settings are presented as a single list. On tablets,
* settings are split by category, with category headers shown to the left of
* the list of settings.
* <p>
* See <a href="http://developer.android.com/design/patterns/settings.html">
* Android Design: Settings</a> for design guidelines and the <a
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings
* API Guide</a> for more information on developing a Settings UI.
*/
public class Settings extends PreferenceActivity {
// From stackoverflow to avoid error API 19
protected boolean isValidFragment(String fragmentName) {
if (ProfilePreferenceFragment.class.getName().equals(fragmentName)) {
return true;
} else if (ChatPreferenceFragment.class.getName().equals(fragmentName)) {
return true;
} else if (NotificationPreferenceFragment.class.getName().equals(
fragmentName)) {
return true;
} else if (ContactPreferenceFragment.class.getName().equals(
fragmentName)) {
return true;
} else if (PaymentPreferenceFragment.class.getName().equals(
fragmentName)) {
return true;
} else if (AccessibilityPreferenceFragment.class.getName().equals(
fragmentName)) {
return true;
} else {
return false;
}
}// From stackoverflow to avoid error API 19
/**
* Determines whether to always show the simplified settings UI, where
* settings are presented in a single list. When false, settings are shown
* as a master/detail two-pane view on tablets. When true, a single pane is
* shown on tablets.
*/
private static final boolean ALWAYS_SIMPLE_PREFS = false;
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
setupSimplePreferencesScreen();
}
/**
* Shows the simplified settings UI if the device configuration
* dictates that a simplified, single-pane UI should be
* shown.
*/
private void setupSimplePreferencesScreen() {
if (!isSimplePreferences(this)) {
return;
}
// In the simplified UI, fragments are not used at all and we instead
// use the older PreferenceActivity APIs.
// Add 'profile' preferences.
addPreferencesFromResource(R.xml.pref_profile);
// Add 'chats' preferences, and a corresponding header.
PreferenceCategory fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.pref_header_chat);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_chat);
// Add 'notification' preferences, and a corresponding header.
fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.pref_header_notification);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_notification);
// Add 'contact' preferences, and a corresponding header.
fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.pref_header_contact);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_contact);
// Add 'payment' preferences, and a corresponding header.
fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.pref_header_payment);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_payment);
// Add 'accessibility' preferences, and a corresponding header.
fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.pref_header_accessibility);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_accesibility);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences to
// their values. When their values change, their summaries are updated
// to reflect the new value, per the Android Design guidelines.
// bindPreferenceSummaryToValue(findPreference("example_text"));
// bindPreferenceSummaryToValue(findPreference("example_list"));
// bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
// bindPreferenceSummaryToValue(findPreference("sync_frequency"));
}
/** {#inheritDoc} */
#Override
public boolean onIsMultiPane() {
return isXLargeTablet(this) && !isSimplePreferences(this);
}
/**
* Helper method to determine if the device has an extra-large screen. For
* example, 10" tablets are extra-large.
*/
private static boolean isXLargeTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
/**
* Determines whether the simplified settings UI should be shown. This is
* true if this is forced via {#link #ALWAYS_SIMPLE_PREFS}, or the device
* doesn't have newer APIs like {#link PreferenceFragment}, or the device
* doesn't have an extra-large screen. In these cases, a single-pane
* "simplified" settings UI should be shown.
*/
private static boolean isSimplePreferences(Context context) {
return ALWAYS_SIMPLE_PREFS
|| Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB
|| !isXLargeTablet(context);
}
/** {#inheritDoc} */
#Override
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
if (!isSimplePreferences(this)) {
loadHeadersFromResource(R.xml.pref_headers, target);
}
}
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference
.setSummary(index >= 0 ? listPreference.getEntries()[index]
: null);
} else if (preference instanceof RingtonePreference) {
// For ringtone preferences, look up the correct display value
// using RingtoneManager.
if (TextUtils.isEmpty(stringValue)) {
// Empty values correspond to 'silent' (no ringtone).
} else {
Ringtone ringtone = RingtoneManager.getRingtone(
preference.getContext(), Uri.parse(stringValue));
if (ringtone == null) {
// Clear the summary if there was a lookup error.
preference.setSummary(null);
} else {
// Set the summary to reflect the new ringtone display
// name.
String name = ringtone
.getTitle(preference.getContext());
preference.setSummary(name);
}
}
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
return true;
}
};
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* #see #sBindPreferenceSummaryToValueListener
*/
private static void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference
.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(
preference,
PreferenceManager.getDefaultSharedPreferences(
preference.getContext()).getString(preference.getKey(),
""));
}
/**
* This fragment shows profile preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class ProfilePreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_profile);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
// bindPreferenceSummaryToValue(findPreference(""));
// bindPreferenceSummaryToValue(findPreference(""));
}
}
/**
* This fragment shows chat preferences only. It is used when the activity
* is showing a two-pane settings UI.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class ChatPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_chat);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("pref_chat_enter_send"));
bindPreferenceSummaryToValue(findPreference("pref_chat_download_message"));
bindPreferenceSummaryToValue(findPreference("pref_chat_download_multimedia"));
bindPreferenceSummaryToValue(findPreference("pref_chat_font_size"));
bindPreferenceSummaryToValue(findPreference("pref_chat_wallpaper"));
bindPreferenceSummaryToValue(findPreference("pref_chat_cloud"));
}
}
/**
* This fragment shows notification preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class NotificationPreferenceFragment extends
PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_notification);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("pref_notification_new_contact"));
bindPreferenceSummaryToValue(findPreference("pref_notification_cat_individual_vibration"));
bindPreferenceSummaryToValue(findPreference("pref_notification_cat_individual_vibration_repeat"));
bindPreferenceSummaryToValue(findPreference("pref_notification_cat_individual_led"));
bindPreferenceSummaryToValue(findPreference("pref_notification_cat_individual_led_repeat"));
bindPreferenceSummaryToValue(findPreference("pref_notification_cat_individual_screen"));
bindPreferenceSummaryToValue(findPreference("pref_notification_cat_individual_screen_repeat"));
bindPreferenceSummaryToValue(findPreference("pref_notification_cat_group_vibration"));
bindPreferenceSummaryToValue(findPreference("pref_notification_cat_group_vibration_repeat"));
bindPreferenceSummaryToValue(findPreference("pref_notification_cat_group_led"));
bindPreferenceSummaryToValue(findPreference("pref_notification_cat_group_led_repeat"));
bindPreferenceSummaryToValue(findPreference("pref_notification_cat_group_screen"));
bindPreferenceSummaryToValue(findPreference("pref_notification_cat_group_screen_repeat"));
}
}
/**
* This fragment shows contact preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class ContactPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_contact);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
// bindPreferenceSummaryToValue(findPreference(""));
// bindPreferenceSummaryToValue(findPreference(""));
}
}
/**
* This fragment shows payment preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class PaymentPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_payment);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
// bindPreferenceSummaryToValue(findPreference(""));
// bindPreferenceSummaryToValue(findPreference(""));
}
}
}
pref_headers.xml
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- These settings headers are only used on tablets. -->
<header
android:fragment="com.example.Settings$ProfilePreferenceFragment"
android:title="#string/pref_header_profile" />
<header
android:fragment="com.example.Settings$ChatPreferenceFragment"
android:title="#string/pref_header_chat" />
<header
android:fragment="com.example.Settings$NotificationPreferenceFragment"
android:title="#string/pref_header_notification" />
<header
android:fragment="com.example.Settings$ContactPreferenceFragment"
android:title="#string/pref_header_contact" />
<header
android:fragment="com.example.Settings$PaymentPreferenceFragment"
android:title="#string/pref_header_payment" />
</preference-headers>
and one section example, others are like this. pref_notification.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<SwitchPreference
android:key="pref_notification_new_contact"
android:summary="#string/pref_notification_new_contact_summary"
android:title="#string/pref_notification_new_contact_title" />
<PreferenceCategory
android:key="pref_notification_cat_individual"
android:title="#string/pref_notification_cat_individual" >
<SwitchPreference
android:defaultValue="true"
android:key="pref_notification_cat_individual_vibration"
android:title="#string/pref_notification_cat_individual_vibration_title" />
<CheckBoxPreference
android:defaultValue="true"
android:dependency="pref_notification_cat_individual_vibration"
android:key="pref_notification_cat_individual_vibration_repeat"
android:summary="#string/pref_notification_cat_individual_vibration_repeat_summary"
android:title="#string/pref_notification_cat_individual_vibration_repeat" />
<SwitchPreference
android:defaultValue="true"
android:key="pref_notification_cat_individual_led"
android:title="#string/pref_notification_cat_individual_led_title" />
<CheckBoxPreference
android:defaultValue="true"
android:dependency="pref_notification_cat_individual_led"
android:key="pref_notification_cat_individual_led_repeat"
android:summary="#string/pref_notification_cat_individual_led_repeat_summary"
android:title="#string/pref_notification_cat_individual_led_repeat" />
<SwitchPreference
android:defaultValue="true"
android:key="pref_notification_cat_individual_screen"
android:title="#string/pref_notification_cat_individual_screen_title" />
<CheckBoxPreference
android:defaultValue="true"
android:dependency="pref_notification_cat_individual_screen"
android:key="pref_notification_cat_individual_screen_repeat"
android:summary="#string/pref_notification_cat_individual_screen_repeat_summary"
android:title="#string/pref_notification_cat_individual_screen_repeat" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_notification_cat_group"
android:title="#string/pref_notification_cat_group" >
<SwitchPreference
android:defaultValue="true"
android:key="pref_notification_cat_group_vibration"
android:title="#string/pref_notification_cat_group_vibration_title" />
<CheckBoxPreference
android:defaultValue="true"
android:dependency="pref_notification_cat_group_vibration"
android:key="pref_notification_cat_group_vibration_repeat"
android:summary="#string/pref_notification_cat_group_vibration_repeat_summary"
android:title="#string/pref_notification_cat_group_vibration_repeat" />
<SwitchPreference
android:defaultValue="true"
android:key="pref_notification_cat_group_led"
android:title="#string/pref_notification_cat_group_led_title" />
<CheckBoxPreference
android:defaultValue="true"
android:dependency="pref_notification_cat_group_led"
android:key="pref_notification_cat_group_led_repeat"
android:summary="#string/pref_notification_cat_group_led_repeat_summary"
android:title="#string/pref_notification_cat_group_led_repeat" />
<SwitchPreference
android:defaultValue="true"
android:key="pref_notification_cat_group_screen"
android:title="#string/pref_notification_cat_group_screen_title" />
<CheckBoxPreference
android:defaultValue="true"
android:dependency="pref_notification_cat_group_screen"
android:key="pref_notification_cat_group_screen_repeat"
android:summary="#string/pref_notification_cat_group_screen_repeat_summary"
android:title="#string/pref_notification_cat_group_screen_repeat" />
</PreferenceCategory>
</PreferenceScreen>
I have a CheckBoxPreference in a FragmentPreference. When the user active the check box, I check if an application is installed and if not, I reset the preference on false and I open the Play Store to download the app.
Basically all works fine, but I have an issue to refresh the UI. Indeed, even if I set the preference on false before opened the Play Store, when the user come back, the box is checked (the fragment has just been paused and resumed so the preference value is ignored).
Is there a way to "refresh" the activity or the fragment?
Make your PreferenceFragment implement the OnSharedPreferenceChangeListener interface.
In onCreate(), you can read the preference value and set the UI accordingly. For instance:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource.
addPreferencesFromResource(R.xml.shakesql_app_prefs);
// Initialize pref summary label.
// Get a reference to the application default shared preferences.
SharedPreferences sp = getPreferenceScreen().getSharedPreferences();
// Read the current preference value.
String listVal =
sp.getString(getString(R.string.preference_font_size_key),
getString(R.string.preference_font_size_default));
// Look up the textual description corresponding to the
// preference value and write it into the summary field.
String listDesc = descriptionFromPref(
listVal,
getResources().getStringArray(
R.array.preference_font_size_values),
getResources().getStringArray(
R.array.preference_font_size_labels)
);
if (!TextUtils.isEmpty(listDesc)) {
ListPreference listPref =
(ListPreference) findPreference(getString(R.string.preference_font_size_key));
listPref.setSummary(listDesc);
}
}
Then, in onSharedPreferenceChanged(), update the UI.
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference pref = findPreference(key);
if (pref instanceof ListPreference) {
// Update display title
// Write the description for the newly selected preference
// in the summary field.
ListPreference listPref = (ListPreference) pref;
CharSequence listDesc = listPref.getEntry();
if (!TextUtils.isEmpty(listDesc)) {
pref.setSummary(listDesc);
}
}
}
Here's a code snippet from the AdvancedPreferences sample in API Demos to force the value of a checkbox preference.
// Toggle the value of mCheckBoxPreference.
if (mCheckBoxPreference != null) {
mCheckBoxPreference.setChecked(!mCheckBoxPreference.isChecked());
}