Process the value of preference before save in Android? - android

I need to crypt my password before save it to local android database. Everything work fine without encryption, I have preferences.xml and so. How can I call a function after I change value of preference (for example, password) ? Here is my code:
public class Preferences extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
// Get the custom preference
Preference customPref = (Preference) findPreference("pass");
customPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener(){
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String crypto = SimpleCrypto.encrypt("MYSECRETKEY", newValue.toString()); // encrypt
// Here is where I'm wrong, I guess.
SharedPreferences settings = getSharedPreferences("preferences", MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString("pass", crypto);
editor.commit();
});
}
}
P.S: Like this, when I change password, it stores password without encryption.

I did this by extending the base EditTextPreference and encrypting/decrypting the password there:
public class EncryptedEditTextPreference extends EditTextPreference {
public EncryptedEditTextPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public EncryptedEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EncryptedEditTextPreference(Context context) {
super(context);
}
#Override
public String getText() {
String value = super.getText();
return SecurityUtils.decrypt(value);
}
#Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
super.setText(restoreValue ? getPersistedString(null) : (String) defaultValue);
}
#Override
public void setText(String text) {
if (Utils.isStringBlank(text)) {
super.setText(null);
return;
}
super.setText(SecurityUtils.encrypt(text));
}
}
There are some calls to my personal utilities, but I think the code is pretty clear in what you need to do.

Related

SwitchButton (in custom view) value is not checked after rotation

I need to create custom view - TextView and Switch button.
I have custom view:
public class CustomTextWithSwitch extends LinearLayout implements View.OnClickListener {
private CustomTextWithSwitchBinding binding;
private boolean defaultValue;
public CustomTextWithSwitch(Context context) {
this(context, null);
}
public CustomTextWithSwitch(Context context, #Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomTextWithSwitch(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
binding = CustomTextWithSwitchBinding.inflate(LayoutInflater.from(getContext()), this);
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CustomTextWithSwitch);
defaultValue = a.getBoolean(R.styleable.CustomTextWithSwitch_defaultValue, false);
a.recycle();
}
#Override
protected void onFinishInflate() {
...
binding.sToggle.setChecked(defaultValue);
super.setOnClickListener(this);
super.onFinishInflate();
}
public void toggle() {
binding.sToggle.toggle();
defaultValue = binding.sToggle.isChecked();
}
#Override
public void onClick(View view) {
toggle();
}
public void setDefaultValue(boolean defaultValue) {
this.defaultValue = defaultValue;
binding.sToggle.setChecked(defaultValue);
}
}
I use that in the activity:
public class MyActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
myCustomView.setDefaultValue(true);
}
}
When I open this activity, everything works as expected - switch button is checked. However, when I rotate the screen, it is checked to false. Can somebody advise what am I doing incorrectly? Note: I use ViewModel and the value is restored correctly. However, the Switch button in this custom view is not toggled.
UPDATE: This issue happens only when I have another CustomTextWithSwich in my activity, so it means they have effect on each other(it seems that default value is set according to second View). Is it possible to separate them, so they are standalone?
I suggest you to use a ViewModdel. During rotation it is normal that you will lost the states. ViewModel will not be destroyed during app rotation so the last state of CustomTextWithSwich will be not lost.
On the other hand you can override onConfigurationChanged method every time app is rotated this method will run, so you can use it to set your data.
#Override
public void onConfigurationChanged(#NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
Please check whether both of your CustomTextWithSwitch and its children on Activity has android:ids. Ids should be different. In this case Android take care about saving instance state for your view.
If it does not save your state, use this code inside your CustomTextWithSwitch
#Override
public Parcelable onSaveInstanceState()
{
Bundle bundle = new Bundle();
bundle.putParcelable("superState", super.onSaveInstanceState());
bundle.putBoolean("isChecked", defaultValue); // ... save check state
return bundle;
}
#Override
public void onRestoreInstanceState(Parcelable state)
{
if (state instanceof Bundle)
{
Bundle bundle = (Bundle) state;
defaultValue = bundle.getBoolean("isChecked"); // ... load state
binding.sToggle.setChecked(defaultValue);
state = bundle.getParcelable("superState");
}
super.onRestoreInstanceState(state);
}
Have faced the same issue. I fixed it by setting setSaveEnabled(false) on the switch view. Just let the viewModel restore it's state.
public CustomTextWithSwitch(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
binding = CustomTextWithSwitchBinding.inflate(LayoutInflater.from(getContext()), this);
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CustomTextWithSwitch);
defaultValue = a.getBoolean(R.styleable.CustomTextWithSwitch_defaultValue, false);
a.recycle();
//Add this (assuming your switch view id is 'switch_view')
binding.switchView.setSaveEnabled(false);
}

Default value of custom DialogPreference is null

I have a TimePreference class that derives from DialogPreference. I'm using 3 NumberPicker to set hours, minutes and seconds. This works fine. But when onSetInitialValue is called defaultValue is always null. Whereas onGetDefaultValue returns the correct value that is defined in the preferences. Any ideas what is wrong?
public TimePreference(Context ctxt, AttributeSet attrs, int defStyle) {
super(ctxt, attrs, defStyle);
setPositiveButtonText(R.string.ok);
setNegativeButtonText(R.string.cancel);
setDialogLayoutResource(R.layout.time_preference_layout);
}
#Override
protected void onBindDialogView(View v) {
super.onBindDialogView(v);
mHoursPicker = (NumberPicker)v.findViewById(R.id.hours);
mHoursPicker.setMinValue(0);
mHoursPicker.setMaxValue(23);
mHoursPicker.setFormatter(TWO_DIGIT_FORMATTER);
mMinutesPicker = (NumberPicker)v.findViewById(R.id.minutes);
mMinutesPicker.setMinValue(0);
mMinutesPicker.setMaxValue(59);
mMinutesPicker.setFormatter(TWO_DIGIT_FORMATTER);
mSecondsPicker = (NumberPicker)v.findViewById(R.id.seconds);
mSecondsPicker.setMinValue(0);
mSecondsPicker.setMaxValue(59);
mSecondsPicker.setFormatter(TWO_DIGIT_FORMATTER);
}
#Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
long currentTimeInMillis = convertTimeToMillis();
if (callChangeListener(currentTimeInMillis)) {
persistLong(currentTimeInMillis);
notifyChanged();
}
}
CharSequence summary = getSummary();
setSummary(summary);
}
#Override
protected Object onGetDefaultValue(TypedArray a, int index) {
super.onGetDefaultValue(a, index);
return a.getString(index);
}
#Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
super.onSetInitialValue(restoreValue, defaultValue);
long value = 0;
if (restoreValue) {
if (defaultValue == null) {
Log.d( "bla", "No default value defined!");
} else {
value = Long.parseLong(getPersistedString((String) defaultValue));
}
} else {
if (defaultValue == null) {
Log.d( "bla", "No default value defined!");
} else {
value = Long.parseLong((String) defaultValue);
}
}
String result = convertMillisToTime(value);
setSummary(result);
}
#Override
public CharSequence getSummary() {
if (mHoursPicker == null) {
return null;
}
return convertTimeToString( mHoursPicker.getValue(), mMinutesPicker.getValue(), mSecondsPicker.getValue());
}
}
Why don't you try setting the default value manually? If you are saving this time value to sharedPreferences, you can specify it in your xml declaration of a PreferenceScreen:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<PreferenceCategory
android:title="#string/pref_cat_general"
android:layout_width="match_parent"
android:layout_height="match_parent">
<to.marcus.rxtesting.ui.widgets.ChoicePreference
android:key="#string/pref_key_sel_time"
android:title="#string/pref_title_time"
android:summary="set time"/>
Notice the custom preference ChoicePreference. Once this is declared, you can define it in its own class, similarly to what you've done above by extending DialogPreference:
public class ChoicePreference extends DialogPreference {
public ChoicePreference(Context context, AttributeSet attrs){
super(context,attrs);
}
#Override
protected void onClick(){
AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
dialog.setTitle("Check Time");
dialog.setMessage("confirm time:");
dialog.setCancelable(true);
dialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getContext(), "time set!", Toast.LENGTH_SHORT).show();
putPrefValue("key_sel_time",true);
}
});
The putPrefValue(key,value) method will write/overwrite your sharedPreference value:
private void putPrefValue(String key, boolean value){
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = prefs.edit();
//removes existing key to trigger change listener
editor.remove(key);
editor.commit();
editor.putBoolean(key, value);
editor.apply();
}
Then from this point you'll need your Activity, for instance, to listen to these sharedPreference changes:
1.) set a listener variable for your sharedPrefs:
private static SharedPreferences sharedPrefs;
private static SharedPreferences.OnSharedPreferenceChangeListener mListener;
2.) register/unregister the listener
#Override
protected void onResume() {
super.onResume();
sharedPrefs.registerOnSharedPreferenceChangeListener(mListener);
}
#Override
protected void onPause() {
super.onPause();
sharedPrefs.unregisterOnSharedPreferenceChangeListener(mListener);
}
3.) get an instance and do something with the result/change
private void initSharedPrefsListener(){
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
mListener = new SharedPreferences.OnSharedPreferenceChangeListener(){
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPrefs, String key){
mBasePresenterImpl.onPrefSelected(key, sharedPrefs.getString(key, "default value here"));
}
};
}
The onPrefSelected method here is conceptual. You can could take the resulting value and persist it to a JsonString.

Android TimePicker in PreferenceScreen -> read the values

I have a custom DialogPreference. The Dialog is called from a PreferenceScreen.
All works fine, the Dialog starts and shows the TimePicker.
But how do I get the selected values?
First of all, I tried to write the selected hours in the summary of the Preference. (therefore the var xxx :)
Later on, I want to save the values in SharedPreferences.
This is what I have for now:
public class Calendar extends DialogPreference implements
TimePicker.OnTimeChangedListener {
TimePicker tp;
int xxx;
public Calendar(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public Calendar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize();
}
private void initialize() {
setPersistent(true);
}
#Override
protected View onCreateDialogView() {
tp = new TimePicker(getContext());
tp.setIs24HourView(true);
return tp;
}
#Override
public void onTimeChanged(TimePicker arg0, int arg1, int arg2) {
}
#Override
public void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
// getEditor().
setTitle(getTitle());
setSummary(Integer.toString(xxx));
}
}
private TimePicker.OnTimeChangedListener mTimeSetListener =
new TimePicker.OnTimeChangedListener() {
#Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
xxx=hourOfDay;
}
};
}
Thanks a lot and best regards
Thanks for asking this question, it provided me with an important answer on how to create a DialogPreference.
I hope I might also have an answer for you. I modified your code a little bit and I can now store the time selected from the Dialog:
#Override
protected View onCreateDialogView() {
this.tp = new TimePicker(getContext());
this.tp.setIs24HourView(true);
final String storedValue = getPersistedString("07:00");
final String[] split = storedValue.split(":");
this.tp.setCurrentHour(Integer.parseInt(split[0]));
this.tp.setCurrentMinute(Integer.parseInt(split[1]));
return this.tp;
}
#Override
public void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
final String result = this.tp.getCurrentHour() + ":" + this.tp.getCurrentMinute();
persistString(result);
}
}
When the dialog is shown I retrieve the stored value and simply set the currentHour and currentMinute fields of the TimePicker. The other way round when the dialog is closed. Since I control both the format on the way in as well as on the way out there should not be a problem with illegal values.
Was this what you were looking for?
To store the value in shared pref, implement on preference Change Listener.
note that preference should be default Shared preference
preferences = PreferenceManager.getDefaultSharedPreferences(context);
editor = preferences.edit();
inside onprefchange:
if (preference.getKey().equals(getString(R.string.reminder_end_time_key))){
editor.putString("End_Date", String.valueOf(newValue));
editor.apply();
endTimePickerPreference.setSummary((CharSequence)newValue);
}

PreferenceActivity: save value as integer

Using a simple EditTextPreference in my preferences activity:
<EditTextPreference
android:key="SomeKey"
android:title="#string/some_title"
android:summary="..."
android:numeric="integer"
android:maxLength="2"
/>
Is there a way that this configuration value would be saved as integer? Seems now it just allows to enter numbers, but the value is still saved as string:
Calling:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
int value = preferences.getInt("SomeKey", -1);
throws me java.lang.ClassCastException: java.lang.String, and:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String value = preferences.getString("SomeKey", "-1");
retrieves the value successfully.
How to make PreferenceActivity to save value as integer by default?
You could extend EditTextPreference:
public class IntEditTextPreference extends EditTextPreference {
public IntEditTextPreference(Context context) {
super(context);
}
public IntEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public IntEditTextPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected String getPersistedString(String defaultReturnValue) {
return String.valueOf(getPersistedInt(-1));
}
#Override
protected boolean persistString(String value) {
return persistInt(Integer.valueOf(value));
}
}
It would be better to overwrite onSetInitialValue() and setText() methods, but then you would have to copy some code from a base class. Above solution is simplier, but it's quite tricky - "string" methods do something with ints. Try to not extend this class further ;-)
You could use it from XML by:
<package.name.IntEditTextPreference
android:key="SomeKey"
android:title="#string/some_title"
android:summary="..."
android:numeric="integer"
android:maxLength="2"
/>
Even if you set android:numeric="integer" it'll be text preference - as its name suggest. You could easily convert string value to int using Integer.valueOf(). Also you could overwrite PreferenceActivity to do conversion automatically on exit.
I think the best solution is to write simple method to get this value from preferences. Something like:
public static int getSomePref(Context context) {
SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(context);
String value = prefs.getString("SomeKey", null);
return value == null ? -1 : Integer.valueOf(value);
}
Then you could very easily use it from your code.
Even though an Answer has been parked accepted I would like to share one more shorter way to achieve this :
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
int value = Integer.parseInt(preferences.getString("SomeKey", "-1"));
Since you have already set that only numbers can be entered this won't through any exception.
yet to complete my answer :
<EditTextPref
android:key="SomeKey"
android:title="#string/some_title"
android:summary="..."
android:numeric="integer"
android:maxLength="2" />
I know this is an old question with an already accepted answer but I think my solution can be helpful for someone searching for a more complete answer. I have just improved #broot answer a litte and there goes my solution:
Override the EditTextPreference to provide text to int conversion:
public class IntEditTextPreference extends EditTextPreference implements EditTextPreference.OnBindEditTextListener {
private String mText;
public IntEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setOnBindEditTextListener(this);
}
public IntEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOnBindEditTextListener(this);
}
public IntEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setOnBindEditTextListener(this);
}
public IntEditTextPreference(Context context) {
super(context);
setOnBindEditTextListener(this);
}
/**
* Saves the text to the current data storage.
*
* #param text The text to save
*/
public void setText(String text) {
final boolean wasBlocking = shouldDisableDependents();
mText = text;
int value = Integer.parseInt(text);
persistInt(value);
final boolean isBlocking = shouldDisableDependents();
if (isBlocking != wasBlocking) {
notifyDependencyChange(isBlocking);
}
notifyChanged();
}
/**
* Gets the text from the current data storage.
*
* #return The current preference value
*/
public String getText() {
return mText;
}
#Override
protected void onSetInitialValue(Object defaultValue) {
int value;
if (defaultValue != null) {
String strDefaultValue = (String) defaultValue;
int defaultIntValue = Integer.parseInt(strDefaultValue);
value = getPersistedInt(defaultIntValue);
} else {
value = getPersistedInt(0);
}
setText(Integer.toString(value));
}
#Override
public boolean shouldDisableDependents() {
return TextUtils.isEmpty(mText) || super.shouldDisableDependents();
}
#Override
public void onBindEditText(#NonNull EditText editText) {
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
}
}
In the preferences xml:
<your.package.here.IntEditTextPreference
android:key="some_key"
android:title="#string/some_title"
android:defaultValue="5"
app:useSimpleSummaryProvider="true"/>
Note: Don't use android:numeric nor android:inputType. Since EditTextPreference is not an EditText itself setting those attributes will do nothing. In order to achieve the desired effect on the EditText from the Dialog opened by the EditTextPreference, just set the input type in your custom EditTextPreference by implementing EditTextPreference.OnBindEditTextListener as you can see in the code above.
That's what worked for me.
I had the same Problem. (I wanted SharedPreference to give me a port number that i stored in a preferences xml file as defaultValue).
Implementing all the SharedPreferences methods would be much effort, so writing a custom method in the class that instanced the SharedPreferences, as broot suggested would be best i think.
You can aswell just use the Static method of Integer in the line where you need it:
int number = Integer.valueOf(settings.getString("myNumberString", "0"));
I think this is the shortest one I could come up with:
int CheckInterval = Integer.parseInt(sharedPreferences.getString("check_frequency","60"));

How do I display the current value of an Android Preference in the Preference summary?

This must come up very often.
When the user is editing preferences in an Android app, I'd like them to be able to see the currently set value of the preference in the Preference summary.
Example: if I have a Preference setting for "Discard old messages" that specifies the number of days after which messages need to be cleaned up. In the PreferenceActivity I'd like the user to see:
"Discard old messages" <- title
"Clean up messages after x days" <- summary where x is the current Preference value
Extra credit: make this reusable, so I can easily apply it to all my preferences regardless of their type (so that it work with EditTextPreference, ListPreference etc. with minimal amount of coding).
There are ways to make this a more generic solution, if that suits your needs.
For example, if you want to generically have all list preferences show their choice as summary, you could have this for your onSharedPreferenceChanged implementation:
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference pref = findPreference(key);
if (pref instanceof ListPreference) {
ListPreference listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry());
}
}
This is easily extensible to other preference classes.
And by using the getPreferenceCount and getPreference functionality in PreferenceScreen and PreferenceCategory, you could easily write a generic function to walk the preference tree setting the summaries of all preferences of the types you desire to their toString representation
Here is my solution... FWIW
package com.example.PrefTest;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceManager;
public class Preferences extends PreferenceActivity implements
OnSharedPreferenceChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
PreferenceManager.setDefaultValues(Preferences.this, R.xml.preferences,
false);
initSummary(getPreferenceScreen());
}
#Override
protected void onResume() {
super.onResume();
// Set up a listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onPause() {
super.onPause();
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
updatePrefSummary(findPreference(key));
}
private void initSummary(Preference p) {
if (p instanceof PreferenceGroup) {
PreferenceGroup pGrp = (PreferenceGroup) p;
for (int i = 0; i < pGrp.getPreferenceCount(); i++) {
initSummary(pGrp.getPreference(i));
}
} else {
updatePrefSummary(p);
}
}
private void updatePrefSummary(Preference p) {
if (p instanceof ListPreference) {
ListPreference listPref = (ListPreference) p;
p.setSummary(listPref.getEntry());
}
if (p instanceof EditTextPreference) {
EditTextPreference editTextPref = (EditTextPreference) p;
if (p.getTitle().toString().toLowerCase().contains("password"))
{
p.setSummary("******");
} else {
p.setSummary(editTextPref.getText());
}
}
if (p instanceof MultiSelectListPreference) {
EditTextPreference editTextPref = (EditTextPreference) p;
p.setSummary(editTextPref.getText());
}
}
}
Android documentation says one can use a String formatting marker in getSummary():
If the summary has a String formatting marker in it (i.e. "%s" or "%1$s"), then the current entry value will be substituted in its place.
Simply specifying android:summary="Clean up messages after %s days" in ListPreference xml declaration worked for me.
Note: This only works for ListPreference.
If you use PreferenceFragment, this is how I solved it. It's self explanatory.
public static class SettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onResume() {
super.onResume();
for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); ++i) {
Preference preference = getPreferenceScreen().getPreference(i);
if (preference instanceof PreferenceGroup) {
PreferenceGroup preferenceGroup = (PreferenceGroup) preference;
for (int j = 0; j < preferenceGroup.getPreferenceCount(); ++j) {
Preference singlePref = preferenceGroup.getPreference(j);
updatePreference(singlePref, singlePref.getKey());
}
} else {
updatePreference(preference, preference.getKey());
}
}
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
updatePreference(findPreference(key), key);
}
private void updatePreference(Preference preference, String key) {
if (preference == null) return;
if (preference instanceof ListPreference) {
ListPreference listPreference = (ListPreference) preference;
listPreference.setSummary(listPreference.getEntry());
return;
}
SharedPreferences sharedPrefs = getPreferenceManager().getSharedPreferences();
preference.setSummary(sharedPrefs.getString(key, "Default"));
}
}
My option is to extend ListPreference and it's clean:
public class ListPreferenceShowSummary extends ListPreference {
private final static String TAG = ListPreferenceShowSummary.class.getName();
public ListPreferenceShowSummary(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ListPreferenceShowSummary(Context context) {
super(context);
init();
}
private void init() {
setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference arg0, Object arg1) {
arg0.setSummary(getEntry());
return true;
}
});
}
#Override
public CharSequence getSummary() {
return super.getEntry();
}
}
Then you add in your settings.xml:
<yourpackage.ListPreferenceShowSummary
android:key="key" android:title="title"
android:entries="#array/entries" android:entryValues="#array/values"
android:defaultValue="first value"/>
You can override default Preference classes and implement the feature.
public class MyListPreference extends ListPreference {
public MyListPreference(Context context) { super(context); }
public MyListPreference(Context context, AttributeSet attrs) { super(context, attrs); }
#Override
public void setValue(String value) {
super.setValue(value);
setSummary(getEntry());
}
}
Later in you xml you can use custom preference like
<your.package.name.MyListPreference
android:key="noteInterval"
android:defaultValue="60"
android:title="Notification Interval"
android:entries="#array/noteInterval"
android:entryValues="#array/noteIntervalValues"
/>
After several hours I've been spent to solve such problem I've implemented this code:
[UPDATE: the final version listing]
public class MyPreferencesActivity extends PreferenceActivity {
...
ListPreference m_updateList;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
m_updateList = (ListPreference) findPreference(getString(R.string.pref_update_interval_key));
String currentValue = m_updateList.getValue();
if (currentValue == null) {
m_updateList.setValue((String)m_updateList.getEntryValues()[DEFAULT_UPDATE_TIME_INDEX]);
currentValue = m_updateList.getValue();
}
updateListSummary(currentValue);
m_updateList.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
updateListSummary(newValue.toString());
return true;
}
});
}
private void updateListSummary(String newValue) {
int index = m_updateList.findIndexOfValue(newValue);
CharSequence entry = m_updateList.getEntries()[index];
m_updateList.setSummary(entry);
}
}
That was the only solution that worked for me fine. Before I've tried to subclass from ListPreferences and to implement android:summary="bla bla bla %s". Neither worked.
Maybe like ListPreference: Modify getSummary to get what you want:
package your.package.preference;
import android.content.Context;
import android.util.AttributeSet;
public class EditTextPreference extends android.preference.EditTextPreference{
public EditTextPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public EditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EditTextPreference(Context context) {
super(context);
}
#Override
public CharSequence getSummary() {
if(super.getSummary() == null) return null;
String summary = super.getSummary().toString();
return String.format(summary, getText());
}
}
And use this in your xml:
<your.package.EditTextPreference
android:key="pref_alpha"
android:summary="Actual value: %s"
android:title="Title"
android:defaultValue="default"
/>
So you are able to write a summary with %s instead of the actual value.
This is the code you need to set the summary to the chosen value. It also sets the values on startup and respects the default values, not only on change. Just change "R.layout.prefs" to your xml-file and extend the setSummary-method to your needs. It actually is only handling ListPreferences, but it is easy to customize to respect other Preferences.
package de.koem.timetunnel;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
public class Prefs
extends PreferenceActivity
implements OnSharedPreferenceChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.addPreferencesFromResource(R.layout.prefs);
this.initSummaries(this.getPreferenceScreen());
this.getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
/**
* Set the summaries of all preferences
*/
private void initSummaries(PreferenceGroup pg) {
for (int i = 0; i < pg.getPreferenceCount(); ++i) {
Preference p = pg.getPreference(i);
if (p instanceof PreferenceGroup)
this.initSummaries((PreferenceGroup) p); // recursion
else
this.setSummary(p);
}
}
/**
* Set the summaries of the given preference
*/
private void setSummary(Preference pref) {
// react on type or key
if (pref instanceof ListPreference) {
ListPreference listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry());
}
}
/**
* used to change the summary of a preference
*/
public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
Preference pref = findPreference(key);
this.setSummary(pref);
}
// private static final String LOGTAG = "Prefs";
}
koem
For EditTextPreference:
public class MyEditTextPreference extends EditTextPreference {
public MyEditTextPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MyEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void setText(String text) {
super.setText(text);
setSummary(text);
}
}
According to Android docs you can use app:useSimpleSummaryProvider="true" in ListPreference and EditTextPreference components.
Actually, CheckBoxPreference does have the ability to specify a different summary based on the checkbox value. See the android:summaryOff and android:summaryOn attributes (as well as the corresponding CheckBoxPreference methods).
If someone is still looking for answers to this, you should check out thirtythreefortys answer.
<ListPreference
android:key="pref_list"
android:title="A list of preferences"
android:summary="%s"
android:entries="#array/pref_list_entries"
android:entryValues="#array/pref_list_entries_values"
android:defaultValue="0" />
Android will replace %s with the current string value of the preference, as displayed by the ListPreference's picker.
Thanks for this tip!
I have one preference screen and want to show the value for each list preference as the summary.
This is my way now:
public class Preferences extends PreferenceActivity implements OnSharedPreferenceChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
#Override
protected void onResume() {
super.onResume();
// Set up initial values for all list preferences
Map<String, ?> sharedPreferencesMap = getPreferenceScreen().getSharedPreferences().getAll();
Preference pref;
ListPreference listPref;
for (Map.Entry<String, ?> entry : sharedPreferencesMap.entrySet()) {
pref = findPreference(entry.getKey());
if (pref instanceof ListPreference) {
listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry());
}
}
// Set up a listener whenever a key changes
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onPause() {
super.onPause();
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference pref = findPreference(key);
if (pref instanceof ListPreference) {
ListPreference listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry());
}
}
This works for me, but I'm wondering what is the best solution (performance, stability, scalibility): the one Koem is showing or this one?
I've seen all voted answers show how to set the summary with the exact current value, but the OP wanted also something like:
"Clean up messages after x days"* <- summary where x is the current Preference value
Here is my answer for achieving that
As per the documentation on ListPreference.getSummary():
Returns the summary of this ListPreference. If the summary has a String formatting marker in it (i.e. "%s" or "%1$s"), then the current
entry value will be substituted in its place.
However, I tried this on several devices and it doesn't seem to work. With some research, I found a good solution in this answer. It simply consists of extending every Preference you use and override getSummary() to work as specified by Android documentation.
Thanks, Reto, for the detailed explanation!
In case this is of any help to anyone, I had to change the code proposed by Reto Meier to make it work with the SDK for Android 1.5
#Override
protected void onResume() {
super.onResume();
// Setup the initial values
mListPreference.setSummary("Current value is " + mListPreference.getEntry().toString());
// Set up a listener whenever a key changes
...
}
The same change applies for the callback function onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
Cheers,
Chris
In Android Studio, open "root_preferences.xml", select Design mode. Select the desired EditTextPreference preference, and under "All attributes", look for the "useSimpleSummaryProvider" attribute and set it to true. It will then show the current value.
I solved the issue with the following descendant of ListPreference:
public class EnumPreference extends ListPreference {
public EnumPreference(Context aContext, AttributeSet attrs) {
super(aContext,attrs);
}
#Override
protected View onCreateView(ViewGroup parent) {
setSummary(getEntry());
return super.onCreateView(parent);
}
#Override
protected boolean persistString(String aNewValue) {
if (super.persistString(aNewValue)) {
setSummary(getEntry());
notifyChanged();
return true;
} else {
return false;
}
}
}
Seems to work fine for me in 1.6 up through 4.0.4.
public class ProfileManagement extends PreferenceActivity implements
OnPreferenceChangeListener {
EditTextPreference screenName;
ListPreference sex;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.layout.profile_management);
screenName = (EditTextPreference) findPreference("editTextPref");
sex = (ListPreference) findPreference("sexSelector");
screenName.setOnPreferenceChangeListener(this);
sex.setOnPreferenceChangeListener(this);
}
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
preference.setSummary(newValue.toString());
return true;
}
}
If you only want to display the plain text value of each field as its summary, the following code should be the easiest to maintain. It requires only two changes (lines 13 and 21, marked with "change here"):
package com.my.package;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
public class PreferencesActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
private final String[] mAutoSummaryFields = { "pref_key1", "pref_key2", "pref_key3" }; // change here
private final int mEntryCount = mAutoSummaryFields.length;
private Preference[] mPreferenceEntries;
#SuppressWarnings("deprecation")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences_file); // change here
mPreferenceEntries = new Preference[mEntryCount];
for (int i = 0; i < mEntryCount; i++) {
mPreferenceEntries[i] = getPreferenceScreen().findPreference(mAutoSummaryFields[i]);
}
}
#SuppressWarnings("deprecation")
#Override
protected void onResume() {
super.onResume();
for (int i = 0; i < mEntryCount; i++) {
updateSummary(mAutoSummaryFields[i]); // initialization
}
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); // register change listener
}
#SuppressWarnings("deprecation")
#Override
protected void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); // unregister change listener
}
private void updateSummary(String key) {
for (int i = 0; i < mEntryCount; i++) {
if (key.equals(mAutoSummaryFields[i])) {
if (mPreferenceEntries[i] instanceof EditTextPreference) {
final EditTextPreference currentPreference = (EditTextPreference) mPreferenceEntries[i];
mPreferenceEntries[i].setSummary(currentPreference.getText());
}
else if (mPreferenceEntries[i] instanceof ListPreference) {
final ListPreference currentPreference = (ListPreference) mPreferenceEntries[i];
mPreferenceEntries[i].setSummary(currentPreference.getEntry());
}
break;
}
}
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
updateSummary(key);
}
}
Here's my solution:
Build a preference type 'getter' method.
protected String getPreference(Preference x) {
// http://stackoverflow.com/questions/3993982/how-to-check-type-of-variable-in-java
if (x instanceof CheckBoxPreference)
return "CheckBoxPreference";
else if (x instanceof EditTextPreference)
return "EditTextPreference";
else if (x instanceof ListPreference)
return "ListPreference";
else if (x instanceof MultiSelectListPreference)
return "MultiSelectListPreference";
else if (x instanceof RingtonePreference)
return "RingtonePreference";
else if (x instanceof SwitchPreference)
return "SwitchPreference";
else if (x instanceof TwoStatePreference)
return "TwoStatePreference";
else if (x instanceof DialogPreference) // Needs to be after ListPreference
return "DialogPreference";
else
return "undefined";
}
Build a 'setSummaryInit' method.
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
Log.i(TAG, "+ onSharedPreferenceChanged(prefs:" + prefs + ", key:" + key + ")");
if( key != null ) {
updatePreference(prefs, key);
setSummary(key);
} else {
Log.e(TAG, "Preference without key!");
}
Log.i(TAG, "- onSharedPreferenceChanged()");
}
protected boolean setSummary() {
return _setSummary(null);
}
protected boolean setSummary(String sKey) {
return _setSummary(sKey);
}
private boolean _setSummary(String sKey) {
if (sKey == null) Log.i(TAG, "Initializing");
else Log.i(TAG, sKey);
// Get Preferences
SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(this);
// Iterate through all Shared Preferences
// http://stackoverflow.com/questions/9310479/how-to-iterate-through-all-keys-of-shared-preferences
Map<String, ?> keys = sharedPrefs.getAll();
for (Map.Entry<String, ?> entry : keys.entrySet()) {
String key = entry.getKey();
// Do work only if initializing (null) or updating specific preference key
if ( (sKey == null) || (sKey.equals(key)) ) {
String value = entry.getValue().toString();
Preference pref = findPreference(key);
String preference = getPreference(pref);
Log.d("map values", key + " | " + value + " | " + preference);
pref.setSummary(key + " | " + value + " | " + preference);
if (sKey != null) return true;
}
}
return false;
}
private void updatePreference(SharedPreferences prefs, String key) {
Log.i(TAG, "+ updatePreference(prefs:" + prefs + ", key:" + key + ")");
Preference pref = findPreference(key);
String preferenceType = getPreference(pref);
Log.i(TAG, "preferenceType = " + preferenceType);
Log.i(TAG, "- updatePreference()");
}
Initialize
Create public class that PreferenceActivity and implements OnSharedPreferenceChangeListener
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PreferenceManager.setDefaultValues(this, R.xml.global_preferences,
false);
this.addPreferencesFromResource(R.xml.global_preferences);
this.getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
protected void onResume() {
super.onResume();
setSummary();
}
Simply:
listPreference.setSummary("%s");
FYI:
findPreference(CharSequence key)
This method was deprecated in API level 11. This function is not relevant
for a modern fragment-based PreferenceActivity.
All the more reason to look at the very slick Answer of #ASD above (source found here) saying to use %s in android:summary for each field in preferences.xml. (Current value of preference is substituted for %s.)
<ListPreference
...
android:summary="Length of longest word to return as match is %s"
...
/>
Since in androidx Preference class has the SummaryProvider interface, it can be done without OnSharedPreferenceChangeListener. Simple implementations are provided for EditTextPreference and ListPreference. Building on EddieB's answer it can look like this. Tested on androidx.preference:preference:1.1.0-alpha03.
package com.example.util.timereminder.ui.prefs;
import android.os.Bundle;
import com.example.util.timereminder.R;
import androidx.preference.EditTextPreference;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceGroup;
/**
* Displays different preferences.
*/
public class PrefsFragmentExample extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences);
initSummary(getPreferenceScreen());
}
/**
* Walks through all preferences.
*
* #param p The starting preference to search from.
*/
private void initSummary(Preference p) {
if (p instanceof PreferenceGroup) {
PreferenceGroup pGrp = (PreferenceGroup) p;
for (int i = 0; i < pGrp.getPreferenceCount(); i++) {
initSummary(pGrp.getPreference(i));
}
} else {
setPreferenceSummary(p);
}
}
/**
* Sets up summary providers for the preferences.
*
* #param p The preference to set up summary provider.
*/
private void setPreferenceSummary(Preference p) {
// No need to set up preference summaries for checkbox preferences because
// they can be set up in xml using summaryOff and summary On
if (p instanceof ListPreference) {
p.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
} else if (p instanceof EditTextPreference) {
p.setSummaryProvider(EditTextPreference.SimpleSummaryProvider.getInstance());
}
}
}
Here,all these are cut from Eclipse sample SettingsActivity.
I have to copy all these too much codes to show how these android developers choose perfectly for more generalized and stable coding style.
I left the codes for adapting the PreferenceActivity to tablet and greater API.
public class SettingsActivity extends PreferenceActivity {
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
setupSummaryUpdatablePreferencesScreen();
}
private void setupSummaryUpdatablePreferencesScreen() {
// 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);
// Bind the summaries of EditText/List/Dialog 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"));
}
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
private String TAG = SettingsActivity.class.getSimpleName();
#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 {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
Log.i(TAG, "pref changed : " + preference.getKey() + " " + value);
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(), ""));
}
}
xml/pref_general.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- NOTE: EditTextPreference accepts EditText attributes. -->
<!-- NOTE: EditTextPreference's summary should be set to its value by the activity code. -->
<EditTextPreference
android:capitalize="words"
android:defaultValue="#string/pref_default_display_name"
android:inputType="textCapWords"
android:key="example_text"
android:maxLines="1"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="#string/pref_title_display_name" />
<!-- NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog todismiss it.-->
<!-- NOTE: ListPreference's summary should be set to its value by the activity code. -->
<ListPreference
android:defaultValue="-1"
android:entries="#array/pref_example_list_titles"
android:entryValues="#array/pref_example_list_values"
android:key="example_list"
android:negativeButtonText="#null"
android:positiveButtonText="#null"
android:title="#string/pref_title_add_friends_to_messages" />
</PreferenceScreen>
values/strings_activity_settings.xml
<resources>
<!-- Strings related to Settings -->
<!-- Example General settings -->
<string name="pref_title_display_name">Display name</string>
<string name="pref_default_display_name">John Smith</string>
<string name="pref_title_add_friends_to_messages">Add friends to messages</string>
<string-array name="pref_example_list_titles">
<item>Always</item>
<item>When possible</item>
<item>Never</item>
</string-array>
<string-array name="pref_example_list_values">
<item>1</item>
<item>0</item>
<item>-1</item>
</string-array>
</resources>
NOTE: Actually I just want to comment like "Google's sample for PreferenceActivity is also interesting". But I haven't enough reputation points.So please don't blame me.
(Sorry for bad English)
You have to use bindPreferenceSummaryToValue function on the onCreate method.
Example:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add 'general' preferences, defined in the XML file
addPreferencesFromResource(R.xml.pref_general);
// For all preferences, attach an OnPreferenceChangeListener so the UI summary can be
// updated when the preference changes.
bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_units_key)));
}
See lesson 3 on Udacity Android Course: https://www.udacity.com/course/viewer#!/c-ud853/l-1474559101/e-1643578599/m-1643578601
For EditTextPreference:
I came to this solution, of course, just if you need particular edittextpreference but you could do this with every Preference:
............
private static final String KEY_EDIT_TEXT_PREFERENCE2 = "on_a1";
public static String value = "";
............
private void updatePreference(Preference preference, String key) {
if (key.equals(KEY_EDIT_TEXT_PREFERENCE2)) {
preference = findPreference(key);
if (preference instanceof EditTextPreference) {
editTextPreference = (EditTextPreference) preference;
editTextPreference.setSummary(editTextPreference.getText());
value = editTextPreference.getText().toString();
return;
}
SharedPreferences sharedPrefs = getPreferenceManager().getSharedPreferences();
preference.setSummary(sharedPrefs.getString(KEY_EDIT_TEXT_PREFERENCE2, ""));
}
}
Then in onResume();
#Override
public void onResume() {
super.onResume();
SharedPreferences etext = getPreferenceManager().getSharedPreferences();
String str = etext.getString("value", "");
editTextPreference = (EditTextPreference) findPreference(KEY_EDIT_TEXT_PREFERENCE2);
editTextPreference.setText(str);
editTextPreference.setSummary(editTextPreference.getText());
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
In:
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
updatePreference(findPreference(key), key);
}
My solution is to create a custom EditTextPreference, used in XML like this: <com.example.EditTextPreference android:title="Example Title" />
EditTextPreference.java:-
package com.example;
import android.content.Context;
import android.util.AttributeSet;
public class EditTextPreference extends android.preference.EditTextPreference
{
public EditTextPreference(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public EditTextPreference(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public EditTextPreference(Context context)
{
super(context, null);
}
#Override
protected void onDialogClosed(boolean positiveResult)
{
super.onDialogClosed(positiveResult);
setSummary(getSummary());
}
#Override
public CharSequence getSummary()
{
return getText();
}
}
If you are using AndroidX you can use a custom SummaryProvider. This approach can be used for any Preference.
Example from documentation (Java):
EditTextPreference countingPreference = (EditTextPreference) findPreference("counting");
countingPreference.setSummaryProvider(new SummaryProvider<EditTextPreference>() {
#Override
public CharSequence provideSummary(EditTextPreference preference) {
String text = preference.getText();
if (TextUtils.isEmpty(text)){
return "Not set";
}
return "Length of saved value: " + text.length();
}
});
Example from documentation (Kotlin):
val countingPreference = findPreference("counting") as EditTextPreference
countingPreference.summaryProvider = SummaryProvider<EditTextPreference> { preference ->
val text = preference.text
if (TextUtils.isEmpty(text)) {
"Not set"
} else {
"Length of saved value: " + text.length
}
}
To set the summary of a ListPreference to the value selected in a dialog you could use this code:
package yourpackage;
import android.content.Context;
import android.util.AttributeSet;
public class ListPreference extends android.preference.ListPreference {
public ListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) setSummary(getEntry());
}
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
super.onSetInitialValue(restoreValue, defaultValue);
setSummary(getEntry());
}
}
and reference the yourpackage.ListPreference object in your preferences.xml remembering to specify there your android:defaultValue as this triggers the call to onSetInitialValue().
If you want you can then modify the text before calling setSummary() to whatever suits your application.

Categories

Resources