As described here, I am subclassing PreferenceFragment and displaying it inside an Activity. That document explains how to listen for preference changes here, but only if yo
Another complete example so you see the entire picture.
public class SettingsActivity extends AppCompatPreferenceActivity {
/**
* 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;
}
};
/**
* 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;
}
/**
* 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(), ""));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setupActionBar();
}
/**
* Set up the {@link android.app.ActionBar}, if the API is available.
*/
private void setupActionBar() {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
// Show the Up button in the action bar.
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
if (!super.onMenuItemSelected(featureId, item)) {
NavUtils.navigateUpFromSameTask(this);
}
return true;
}
return super.onMenuItemSelected(featureId, item);
}
/**
* {@inheritDoc}
*/
@Override
public boolean onIsMultiPane() {
return isXLargeTablet(this);
}
/**
* {@inheritDoc}
*/
@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.pref_headers, target);
}
/**
* This method stops fragment injection in malicious applications.
* Make sure to deny any unknown fragments here.
*/
protected boolean isValidFragment(String fragmentName) {
return PreferenceFragment.class.getName().equals(fragmentName)
|| GPSLocationPreferenceFragment.class.getName().equals(fragmentName)
|| DataSyncPreferenceFragment.class.getName().equals(fragmentName)
|| NotificationPreferenceFragment.class.getName().equals(fragmentName);
}
////////////////// NEW PREFERENCES ////////////////////////////
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GPSLocationPreferenceFragment extends PreferenceFragment {
Preference prefGPSServerAddr, prefGPSASDID, prefIsGPSSwitch;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_gps_location);
setHasOptionsMenu(true);
// 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("gpsServer_Addr"));
bindPreferenceSummaryToValue(findPreference("gpsASD_ID"));
prefGPSServerAddr = findPreference("gpsServer_Addr");
prefGPSServerAddr.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
try {
// do whatever you want with new value
}
catch (Exception ex)
{
Log.e("Preferences", ex.getMessage());
}
// true to update the state of the Preference with the new value
// in case you want to disallow the change return false
return true;
}
});
prefGPSASDID = findPreference("gpsASD_ID");
prefGPSASDID.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
try {
// do whatever you want with new value
}
catch (Exception ex)
{
Log.e("Preferences", ex.getMessage());
}
// true to update the state of the Preference with the new value
// in case you want to disallow the change return false
return true;
}
});
prefIsGPSSwitch = findPreference("isGPS_Switch");
prefIsGPSSwitch.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
try {
// do whatever you want with new value
}
catch (Exception ex)
{
Log.e("Preferences", ex.getMessage());
}
// true to update the state of the Preference with the new value
// in case you want to disallow the change return false
return true;
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
boolean tabletSize = getResources().getBoolean(R.bool.isTablet);
if (tabletSize) {
startActivity(new Intent(getActivity(), MainActivity.class));
} else {
startActivity(new Intent(getActivity(), SettingsActivity.class));
}
return true;
}
return super.onOptionsItemSelected(item);
}
}
///////////////////////////////////////////////////////////////
/**
* 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);
setHasOptionsMenu(true);
// 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"));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
boolean tabletSize = getResources().getBoolean(R.bool.isTablet);
if (tabletSize) {
startActivity(new Intent(getActivity(), MainActivity.class));
} else {
startActivity(new Intent(getActivity(), SettingsActivity.class));
}
return true;
}
return super.onOptionsItemSelected(item);
}
}
/**
* 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);
setHasOptionsMenu(true);
// 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) {
int id = item.getItemId();
if (id == android.R.id.home) {
boolean tabletSize = getResources().getBoolean(R.bool.isTablet);
if (tabletSize) {
startActivity(new Intent(getActivity(), MainActivity.class));
} else {
startActivity(new Intent(getActivity(), SettingsActivity.class));
}
return true;
}
return super.onOptionsItemSelected(item);
}
}
}
Here is one way to do it and avoid any potential memory leaks:
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.pref_movies);
SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
//starts live change listener
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onDestroyView () {
super.onDestroyView();
//Unregisters listener here
PreferenceManager.getDefaultSharedPreferences(getContext())
.unregisterOnSharedPreferenceChangeListener(this);
}
If you only want to update the summary, using androidx preference library (see the official guides), and adding the following attribute in your layout xml will be enough:
<EditTextPreference
...
app:useSimpleSummaryProvider="true" />