preferencefragmentcompat - ¿Cómo muestro el valor actual de una preferencia de Android en el resumen de preferencias?
setting layout in android (30)
Esto debe surgir muy a menudo.
Cuando el usuario está editando las preferencias en una aplicación de Android, me gustaría que puedan ver el valor establecido actualmente de la preferencia en el resumen de Preference
.
Ejemplo: si tengo una configuración de Preferencia para "Descartar mensajes antiguos" que especifica el número de días después de los cuales se deben limpiar los mensajes. En PreferenceActivity
me gustaría que el usuario vea:
"Descartar mensajes antiguos" <- título
"Limpiar mensajes después de x días" <- summary donde x es el valor de preferencia actual
Crédito adicional: haga que sea reutilizable, de modo que pueda aplicarlo fácilmente a todas mis preferencias, independientemente de su tipo (para que funcione con EditTextPreference, ListPreference, etc., con una cantidad mínima de codificación).
Para 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);
}
}
Aquí está mi solución ... 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());
}
}
}
Aquí está mi solución:
Construye un método ''getter'' de tipo de preferencia.
protected String getPreference(Preference x) {
// http://.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";
}
Construye un método ''setSummaryInit''.
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://.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()");
}
Inicializar
Cree una clase pública que PreferenceActivity e implemente 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();
}
Aquí, todos estos se cortan de Eclipse sample SettingsActivity
. Tengo que copiar todos estos demasiados códigos para mostrar cómo estos desarrolladores de Android eligen perfectamente para un estilo de codificación más generalizado y estable.
Dejé los códigos para adaptar PreferenceActivity
a la tableta y una API mayor.
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>
NOTA: En realidad, solo quiero comentar como "La muestra de Google para PreferenceActivity también es interesante". Pero no tengo suficientes puntos de reputación. Así que, por favor, no me culpes.
(Perdón por el mal inglés)
Después de varias horas que he dedicado a resolver este problema, he implementado este código:
[ACTUALIZACIÓN: el listado de la versión final]
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);
}
}
Esa fue la única solución que funcionó bien para mí. Antes de intentar subclasificar de ListPreferences e implementar android: summary = "bla bla bla% s". Tampoco funcionó.
En realidad, CheckBoxPreference tiene la capacidad de especificar un resumen diferente basado en el valor de la casilla de verificación. Consulte los atributos de android: summaryOff y android: summaryOn (así como los correspondientes métodos CheckBoxPreference).
Este es el código que necesita para establecer el resumen en el valor elegido. También establece los valores en el inicio y respeta los valores predeterminados, no solo en el cambio. Simplemente cambie "R.layout.prefs" a su archivo xml y extienda el método setSummary a sus necesidades. En realidad, solo se trata de ListPreferences, pero es fácil de personalizar para respetar otras Preferencias.
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
Gracias por este consejo!
Tengo una pantalla de preferencias y quiero mostrar el valor de cada preferencia de lista como resumen.
Este es mi camino ahora:
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());
}
}
Esto me funciona, pero me pregunto cuál es la mejor solución (rendimiento, estabilidad, escalabilidad): ¿la que está mostrando Koem o esta?
Gracias, Reto, por la explicación detallada!
En caso de que esto sea de alguna ayuda para alguien, tuve que cambiar el código propuesto por Reto Meier para que funcione con el SDK para 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
...
}
El mismo cambio se aplica a la función de devolución de llamada onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
Aclamaciones,
Chris
Hay formas de hacer que esta sea una solución más genérica, si se adapta a sus necesidades.
Por ejemplo, si desea que todas las preferencias de la lista muestren su elección como resumen, puede tener esto para su implementación onSharedPreferenceChanged
:
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference pref = findPreference(key);
if (pref instanceof ListPreference) {
ListPreference listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry());
}
}
Esto es fácilmente extensible a otras clases de preferencia.
Y al utilizar las funciones getPreferenceCount
y getPreference
en PreferenceScreen
y PreferenceCategory
, puede escribir fácilmente una función genérica para recorrer el árbol de preferencias y establecer los resúmenes de todas las preferencias de los tipos que desea para su representación en toString
He visto que todas las respuestas votadas muestran cómo configurar el resumen con el valor actual exacto, pero el OP también quería algo como:
"Limpiar mensajes después de x días" * <- resumen donde x es el valor de preferencia actual
Aquí está mi respuesta para lograr eso
Como dice la documentation sobre ListPreference.getSummary()
:
Devuelve el resumen de este ListPreference. Si el resumen tiene un marcador de formato de cadena (es decir, "% s" o "% 1 $ s"), el valor de la entrada actual se sustituirá en su lugar.
Sin embargo, lo probé en varios dispositivos y no parece funcionar. Con algunas investigaciones, encontré una buena solución en esta respuesta . Simplemente consiste en extender cada Preference
que usa y anular getSummary()
para que funcione según lo especificado por la documentación de Android.
La documentation Android dice que se puede usar un marcador de formato de cadena en getSummary()
:
Si el resumen tiene un marcador de formato de cadena (es decir, "% s" o "% 1 $ s"), el valor de la entrada actual se sustituirá en su lugar.
Simplemente especificando android:summary="Clean up messages after %s days"
en la declaración xml de ListPreference funcionó para mí.
Nota: Esto solo funciona para ListPreference
.
Mi opción es extender ListPreference y está limpio:
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();
}
}
Luego agregas en tu configuración.xml:
<yourpackage.ListPreferenceShowSummary
android:key="key" android:title="title"
android:entries="@array/entries" android:entryValues="@array/values"
android:defaultValue="first value"/>
Para tu información:
findPreference(CharSequence key)
This method was deprecated in API level 11. This function is not relevant
for a modern fragment-based PreferenceActivity.
Más razones para ver la muy elegante Answer
de @ASD anterior ( fuente encontrada aquí ) que dice usar %s
en android:summary
para cada campo en preferences.xml
. (El valor actual de preferencia se sustituye por %s
.)
<ListPreference
...
android:summary="Length of longest word to return as match is %s"
...
/>
Puede anular las clases de Preferencia predeterminadas e implementar la función.
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());
}
}
Más adelante en tu xml puedes usar preferencias personalizadas como
<your.package.name.MyListPreference
android:key="noteInterval"
android:defaultValue="60"
android:title="Notification Interval"
android:entries="@array/noteInterval"
android:entryValues="@array/noteIntervalValues"
/>
Resolví el problema con el siguiente descendiente de 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;
}
}
}
Parece funcionar bien para mí en 1.6 hasta 4.0.4.
Si alguien todavía está buscando respuestas a esto, debe verificar la respuesta de thirtythreeforty y thirtythreeforty s.
<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 reemplazará% s con el valor de cadena actual de la preferencia, como lo muestra el selector ListPreference.
Si solo desea mostrar el valor de texto sin formato de cada campo como resumen, el siguiente código debe ser el más fácil de mantener. Requiere solo dos cambios (líneas 13 y 21, marcados con "cambiar aquí"):
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);
}
}
Si usas PreferenceFragment
, así es como lo resolví. Es auto explicativo.
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"));
}
}
Simplemente:
listPreference.setSummary("%s");
Tal vez como ListPreference: modifique getSummary para obtener lo que desea:
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());
}
}
Y usa esto en tu xml:
<your.package.EditTextPreference
android:key="pref_alpha"
android:summary="Actual value: %s"
android:title="Title"
android:defaultValue="default"
/>
Por lo tanto, puede escribir un resumen con %s
lugar del valor real.
Debe utilizar la función bindPreferenceSummaryToValue en el método onCreate.
Ejemplo:
@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)));
}
Vea la lección 3 en el Curso de Android de Udacity: https://www.udacity.com/course/viewer#!/c-ud853/l-1474559101/e-1643578599/m-1643578601
La solución concisa por 1 línea de código:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
bindPreferenceSummaryToValue(findPreference("mySetting"));
// initialize summary
sBindPreferenceSummaryToValueListener.onPreferenceChange(findPreference("mySetting"),
((ListPreference) findPreference("mySetting")).getEntry());
}
Aquí hay una solución de trabajo para todas EditTextPreference
las PreferenceFragment
respuestas dentro de una respuesta basada en @tdeveaux:
public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "SettingsFragment";
@Override
public void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onResume () {
super.onResume();
for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); ++i) {
Preference preference = getPreferenceScreen().getPreference(i);
updatePreference(preference);
}
}
@Override
public void onSharedPreferenceChanged (SharedPreferences sharedPreferences, String key) {
updatePreference(findPreference(key));
}
private void updatePreference (Preference preference) {
if (preference instanceof EditTextPreference) {
EditTextPreference editTextPreference = (EditTextPreference)preference;
editTextPreference.setSummary(editTextPreference.getText());
}
}
}
Debido a que estoy usando una costumbre PreferenceDataStore
, no puedo agregar un oyente a algunos, SharedPreference
así que tuve que escribir una solución un tanto intrépida que escucha cada preferencia:
class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChangeListener {
private val handler: Handler by lazy { Handler(Looper.getMainLooper()) }
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
preferenceManager.preferenceDataStore = prefs
addPreferencesFromResource(R.xml.app_preferences)
onPreferenceChange(preferenceScreen, null)
}
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
preference.onPreferenceChangeListener = this
when (preference) {
is PreferenceGroup -> for (i in 0 until preference.preferenceCount) {
onPreferenceChange(preference.getPreference(i), null)
}
is ListPreference -> {
if (preference.value == null) {
preference.isPersistent = false
preference.value = Preference::class.java.getDeclaredField("mDefaultValue")
.apply { isAccessible = true }
.get(preference).toString()
preference.isPersistent = true
}
postPreferenceUpdate(Runnable { preference.summary = preference.entry })
}
}
return true
}
/**
* We can''t directly update the preference summary update because [onPreferenceChange]''s result
* is used to decide whether or not to update the pref value.
*/
private fun postPreferenceUpdate(r: Runnable) = handler.post(r)
}
Encontré esta forma de hacer EditTextPreference
desde el soporte de la biblioteca de soporte técnico "%s"
en resumen (como ListPreference
ya se maneja):
public class EditTextPreference extends android.support.v7.preference.EditTextPreference {
public EditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void setText(String text) {
super.setText(text);
notifyChanged();
}
@Override
public CharSequence getSummary() {
String text = super.getText();
String summary = super.getSummary().toString();
return String.format(summary, text == null ? "" : text);
}
}
En xml se verá así:
<com.example.yourapp.EditTextPreference
android:defaultValue="1"
android:key="cleanup_period"
android:summary="Clean up messages after %s days"
android:title="Clean up period" />
Mi solución es crear un personalizado EditTextPreference
, utilizado en XML como este:<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();
}
}
Para EditTextPreference :
Llegué a esta solución, por supuesto, solo si necesita una referencia de edición de texto particular, pero podría hacer esto con cada Preferencia:
............
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, ""));
}
}
Luego en 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);
}
En:
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
updatePreference(findPreference(key), key);
}
Para establecer el resumen de ListPreference
a en el valor seleccionado en un diálogo, puede usar este código:
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());
}
}
y haga referencia al yourpackage.ListPreference
objeto en su preferences.xml
memoria para especificar allí su android:defaultValue
como esto activa la llamada a onSetInitialValue()
.
Si lo desea, puede modificar el texto antes de llamar setSummary()
a lo que se adapte a su aplicación.
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;
}
}