¿Cómo se actualiza PreferenceActivity para mostrar los cambios en la configuración?


Basado en el siguiente código, ¿puede decirme cómo actualizar la ventana de PreferenceActivity para mostrar los cambios en la configuración inmediatamente? Por ejemplo: el usuario toca la casilla master chime toggle a true (marcada), me gustaría que el usuario vea inmediatamente las otras configuraciones, como la casilla ChimeOn15Past, también sea true (marcada)

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.";
}
Author: Bhargav Rao, 2011-11-04

10 answers

La respuesta de Nikolay es correcta. Sólo quiero añadir un poco de 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 del almacenamiento persistente una vez que se inicia. En lugar de usar SharedPreferences.Editor para modificar y confirmar cambios adicionales como lo hizo en su código, es mejor hacer los cambios en el objeto local PreferenceManager que será confirmado por el PreferenceActivity en su ciclo de vida normal.

 27
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-07 03:02:12

En lugar de

finish();
startActivity(getIntent());

Prefiero el siguiente código :

setPreferenceScreen(null);
addPreferencesFromResource(R.xml.preferences);

Esto también restablecerá la pantalla, pero sin el procedimiento completo finish 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.

EDITAR: setPreferenceScreen está en desuso en PreferenceActivity (todavía trabajando) pero no está en PreferenceFragment

 40
Author: Solostaran14,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-27 13:42:21

Hay un método simple 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ás la posición de ListView.

 11
Author: Marcel Wesołowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-28 09:04:26

Implementa onPreferenceChange y cambia los perfs relacionados desde allí. Para 'refrescar' toda la actividad, necesita finish() y reiniciarla.

 3
Author: Nikolay Elenkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-04 02:34:12

Después de luchar contra esto por un día, me di cuenta de esto.
Esto es para múltiples niveles de preferencias.

parent es la pantalla de preferencias que contiene la preferencia que está intentando actualizar.

Dado que la pantalla de configuración se muestra como un diálogo, puede obtener la vista de lista desde el diálogo, luego decirle a su adaptador que actualice hijo.

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 antiguos, pero esto funciona

    ListAdapter adapter = parent.getRootAdapter();
    if (adapter instanceof BaseAdapter) {
        ((BaseAdapter)adapter).notifyDataSetChanged();
    }
 1
Author: Sailforms Developer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-23 18:26:11

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 con esta manera.

 1
Author: Arda Ç.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-29 18:37:54

Esta clase indica pantalla de preferencias 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);
        }
    }
 0
Author: Vinil Chandran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-15 20:17:10

Me las arreglé para escribir un método que en realidad es bastante simple y sin necesidad de invalidar las vistas de lista o cualquiera que sea la situación. Este método hace una llamada a la public ViewGroup removeView(View view), View requestLayout(), View forceLayout(), ViewGroup addView(View view), y finalmente una llamada a los métodos Fragment OnCreate(Bundle savedInstanceState) con algunas comprobaciones null y una variable temporal final View para almacenar la vista real cuando se elimina la vista.

Este método es todavía bastante nuevo y voy a darle algunos ajustes y refinación en los próximos 2 días, pero funciona perfectamente como es sin efectos secundarios. Dado que la clase que he escrito sosteniendo el código cambia el título de preferencia real y los estilos de texto de resumen para toda la rom (ese fue el punto de las opciones que he agregado), también he agregado un constructor público las clases que son actividades que se encuentran en la pila de actividades debajo de la pantalla de estilo de preferencia para que puedan actualizarse al mismo tiempo. Lo más probable es que esté moviendo este nuevo método en la clase de vista de marcos para que pueda estar disponible sistema amplio.

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 variables de vista se establecen inicialmente en la inicialización de la clase y se inicializan y definen en el View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) y el View onViewCreated(View view, Bundle savedInstanceState). Las 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 de la pila a continuación, mi clase PreferenceStyle, establecí un constructor vacío que se puede inicializar en cualquier lugar 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 puse como una variable anterior a 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 mi método reloadView(View view) pero la variable view utilizada para hacer la llamada es una variable View establecida inmediatamente antes de la llamada y se establece como null:

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 local variables:

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 View 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 involucre múltiples clases utilizadas como utils. Si alguien tiene alguna sugerencia de comentario para simplificar o lo que sea, siéntase libre de comentar.

 0
Author: cphelps76,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-28 22:30:27

Después de confirmar los cambios en SharedPreferences, creo que debería llamar a invalidateHeaders.

 0
Author: android developer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-11 12:31:51

Si te diriges a API 11 y superior, puedes usar invalidateHeaders.

De los documentos:

Llame cuando necesite cambiar los encabezados que se muestran. Traducirá in onBuildHeaders () se llama más tarde para recuperar la nueva lista.

 -1
Author: marmor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-19 10:54:45