preferencias - preferencefragment android
¿Cómo actualiza PreferenceActivity para mostrar los cambios en la configuración? (10)
Después de confirmar los cambios en las SharedPreferences, creo que debería llamar a invalidateHeaders
.
Basado en el siguiente código, ¿puede decirme cómo actualizar la ventana de PreferenceActivity para mostrar los cambios en la configuración de inmediato? Por ejemplo: el usuario toca la casilla de verificación de activación del timbre maestro en verdadero (marcado), me gustaría que el usuario vea inmediatamente las otras configuraciones, como la casilla de verificación ChimeOn15Past también sea verdadero (marcado)
SharedPreferences.Editor prefEditor = clockSettings.edit(); // Allow the settings to be changed.
if (booleanMasterChimeToggle == true) {
prefEditor.putBoolean("ChimeOnTheHour", true);
prefEditor.putBoolean("ChimeOn15Past", true);
prefEditor.putBoolean("ChimeOn30Past", true);
prefEditor.putBoolean("ChimeOn45Past", true);
strNotifyMessage = "Full chiming has now been set.";
} else {
prefEditor.putBoolean("ChimeOnTheHour", false);
prefEditor.putBoolean("ChimeOn15Past", false);
prefEditor.putBoolean("ChimeOn30Past", false);
prefEditor.putBoolean("ChimeOn45Past", false);
strNotifyMessage = "Full chiming has now been disabled.";
}
Después de pelear esto por un día, me di cuenta de esto.
Esto es para múltiples niveles de preferencias.
padre es la pantalla de preferencias que contiene la preferencia que está intentando actualizar.
Dado que la pantalla de configuración se muestra como un cuadro de diálogo, puede obtener la vista de lista del cuadro de diálogo y luego decirle a su adaptador que actualice la versión secundaria .
PreferenceScreen parent // The screen holding the child
PreferenceScreen child // The entry changing
child.setSummary(isEnabled?"Enabled":"Not Enabled");
ListView v = (ListView)parent.getDialog().findViewById(android.R.id.list);
BaseAdapter ba = (BaseAdapter)v.getAdapter();
ba.notifyDataSetChanged();
Encontré que R.id.list no está disponible en teléfonos más antiguos pero esto funciona
ListAdapter adapter = parent.getRootAdapter();
if (adapter instanceof BaseAdapter) {
((BaseAdapter)adapter).notifyDataSetChanged();
}
En lugar de
finish();
startActivity(getIntent());
Prefiero el siguiente código:
setPreferenceScreen(null);
addPreferencesFromResource(R.xml.preferences);
Esto restablecerá la pantalla también, pero sin el procedimiento de acabado completo y sus consecuencias. Además, este código funciona bien con PreferenceActivity
y PreferenceFragment
.
Esto es interesante si desea cambiar dinámicamente el valor de la configuración regional, por ejemplo. En este caso, trabajar con el administrador no es suficiente porque desea una recarga completa de títulos y valores.
EDIT: setPreferenceScreen
está en desuso en PreferenceActivity
(aún funciona) pero no está en PreferenceFragment
Esta clase indica la pantalla de preferencia simple. Lo que puede ayudarte.
public class PreferenceActivitySettings extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
private SharedPreferences preferences;
@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
preferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
preferences.registerOnSharedPreferenceChangeListener(this);
}
@SuppressWarnings("deprecation")
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
setPreferenceScreen(null);
addPreferencesFromResource(R.xml.settings);
}
}
Hay un método sencillo para actualizar todos los elementos de la lista a la vez. Simplemente haga lo siguiente:
getPreferenceScreen().removeAll();
addPreferencesFromResource(R.xml.preferences);
Con este enfoque no perderá la posición de ListView.
Implementar onPreferenceChange
y alternar los perfs relacionados desde allí. Para ''actualizar'' toda la actividad, debe finish()
y reiniciarla.
La respuesta de Nikolay es correcta. Solo quiero agregar un código aquí para ilustrar su punto más claramente.
private CheckBoxPreference mOn15Past;
private CheckBoxPreference mOn30Past;
private CheckBoxPreference mOn45Past;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
mOn15Past = (CheckBoxPreference) findPreference("ChimeOn15Past");
mOn30Past = (CheckBoxPreference) findPreference("ChimeOn30Past");
mOn45Past = (CheckBoxPreference) findPreference("ChimeOn45Past");
final Preference chimeMaster = findPreference("ChimeMaster");
chimeMaster.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newVal) {
final boolean value = (Boolean) newVal;
mOn15Past.setChecked(value);
mOn30Past.setChecked(value);
mOn45Past.setChecked(value);
return true;
}
});
}
En resumen, PreferenceActivity
no está diseñado para actualizar sus valores desde el almacenamiento persistente una vez que se inicia. En lugar de utilizar SharedPreferences.Editor
para modificar y confirmar cambios adicionales como lo hizo en su código, es mejor realizar los cambios en el objeto PreferenceManager
local que se realizará con la actividad PreferenceActivity
en su ciclo de vida normal.
Logré escribir un método que en realidad es bastante simple y sin necesidad de invalidar ListViews o cualquiera que sea la situación. Este método realiza una llamada al public ViewGroup removeView(View view)
, View requestLayout()
, View forceLayout()
, ViewGroup addView(View view)
y, finalmente, una llamada a Fragment OnCreate(Bundle savedInstanceState)
con algunas comprobaciones nulas y una variable temporal de final View
para almacenar la vista real cuando se elimina la vista.
Este método todavía es bastante nuevo y lo estaré modificando y afinando en los próximos 2 días, pero funciona perfectamente, sin efectos secundarios. Dado que la clase que he escrito manteniendo el código cambia el estilo de preferencia real y los estilos de texto de resumen para toda la ROM (ese fue el punto de las opciones que agregué), también agregué a un constructor público las clases que son actividades que se encuentran en la pila de actividades debajo de la pantalla de estilo de preferencias para que puedan actualizarse al mismo tiempo. Probablemente moveré este nuevo método a la clase de vista de marcos para que pueda estar disponible en todo el sistema.
public void reLoadView(View view) {
if (view == null) {
view = mView;
Log.i(TAG, "The current View is: " + view);
}
final View tmpView = view;
try {
setStyleChanged(1);
setReset(0);
Log.i(TAG, "The Temporary View is: " + tmpView);
Log.i(TAG, "The current View is: " + mView);
Log.i(TAG, "The current ViewGroup is: " + mViewGroup);
if (mView != null) {
if (mViewGroup != null) {
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mViewGroup.removeView(mView);
mView.requestLayout();
mView.forceLayout();
mViewGroup.addView(tmpView);
onCreate(new Bundle());
}
});
}
}
View tmp = null;
mDemented.reLoadView(tmp);
} catch (Exception e) {
}
}
Las propias variables de vista se configuran inicialmente en la inicialización de la clase y se inicializan y se definen en la View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
y la View onViewCreated(View view, Bundle savedInstanceState)
Las propias variables de vista se establecen inicialmente en la inicialización de la clase.
private View mView;
private ViewGroup mViewGroup;
private int mLayoutResId = R.layout.preference_list_fragment;//holds the layout reference just to keep it clean
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View rootView = inflater.inflate(mLayoutResId, parent, false);
mViewGroup = parent;
return rootView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
mView = view;
}
En las actividades en la pila de abajo, mi clase PreferenceStyle, establezco un constructor vacío que puede inicializarse en cualquier parte de la aplicación.
public class DEMENTED extends SettingsPreferenceFragment implements
Preference.OnPreferenceChangeListener, View.OnClickListener {
public DEMENTED() {
super();
}
//other code to do whatever here
En mi clase PreferenceStyle, importé mi clase DEMENTED y luego la configuré como una variable antes de onCreate(Bundle savedInstanceState)
:
private DEMENTED mDemented;
Luego inicializó la variable en onCreate(Bundle savedInstanceState)
:
mDemented = new DEMENTED();
La llamada a mi clase DEMENTED para recargar su vista se realiza en el reloadView(View view)
, pero la vista de variable utilizada para realizar la llamada es una variable de vista establecida inmediatamente antes de la llamada y se establece como nula:
View tmp = null;
mDemented.reLoadView(tmp);
y mi clase DEMENTED comprueba si la Vista incluida en la llamada al método es nula y, si es así, la establece en una variable de Vista localizada para que el método pueda hacer su trabajo con las variables locales:
public void reLoadView(View view) {
if (view == null) {
view = mView;
Log.i(TAG, "The current View is: " + view);
}
//all the other good stuff here
Básicamente, esto usa el ViewGroup como se define en onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
:
mViewGroup = parent;
y la variable de onViewCreated(View view, Bundle savedInstanceState)
se establece en onViewCreated(View view, Bundle savedInstanceState)
mView = view;
Espero que esto ayude a alguien porque esta ha sido una pregunta que he visto repetida aquí una y otra vez y todavía tengo que encontrar una solución sólida básicamente en cualquier lugar que no implique varias clases utilizadas como utils. Si alguien tiene alguna sugerencia de comentarios para simplificar o lo que sea, no dude en comentar.
Si está apuntando a API 11 y superior, puede usar invalidateHeaders
.
De la documentación:
Llame cuando necesite cambiar los encabezados que se muestran. Como resultado, se llamará a onBuildHeaders () más tarde para recuperar la nueva lista.
Simplemente puede llamar al método onCreate. Si lo desea, puede llamar a los métodos onStart y onResume.
onCreate(null);
He resuelto mi problema de esta manera.