Как обновить PreferenceActivity, чтобы показать изменения в настройках? - PullRequest
27 голосов
/ 04 ноября 2011

Основываясь на следующем коде, можете ли вы сказать мне, как обновить окно PreferenceActivity, чтобы немедленно отобразить изменения в настройках?Например: пользователь устанавливает флажок основного переключателя перезвона в значение true (отмечен галочкой), я бы хотел, чтобы пользователь сразу увидел, что другие параметры, такие как флажок ChimeOn15Past, также будут иметь значение true (отмечен галочкой)

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.";
}

Ответы [ 10 ]

39 голосов
/ 15 ноября 2012

вместо

finish();
startActivity(getIntent());

Я предпочитаю следующий код:

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

Это также сбросит отображение, но без всей процедуры финиша и ее последствий. Плюс этот код хорошо работает с PreferenceActivity и PreferenceFragment.

Это интересно, если вы хотите динамически изменить значение локали, например. В этом случае недостаточно работать с менеджером, поскольку требуется полная перезагрузка заголовков и значений.

РЕДАКТИРОВАТЬ: setPreferenceScreen устарела в PreferenceActivity (все еще работает), но не в PreferenceFragment

29 голосов
/ 05 ноября 2011

Николай ответ правильный.Я просто хочу добавить сюда некоторый код, чтобы проиллюстрировать его точку зрения.

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;
        }

    });
}

Короче говоря, PreferenceActivity не предназначен для обновления своих значений из постоянного хранилища после его запуска.Вместо использования SharedPreferences.Editor для изменения и фиксации дополнительных изменений, как вы делали в своем коде, лучше вносить изменения в локальный объект PreferenceManager, который будет зафиксирован PreferenceActivity в его обычном жизненном цикле.

13 голосов
/ 28 июля 2015

Существует простой способ обновить все элементы списка одновременно.Просто сделайте следующее:

getPreferenceScreen().removeAll();
addPreferencesFromResource(R.xml.preferences);

При таком подходе вы не потеряете позицию ListView.

3 голосов
/ 04 ноября 2011

Реализация onPreferenceChange и переключение связанных перфораций оттуда.Чтобы «обновить» все упражнение, вам нужно finish() и перезапустить его.

1 голос
/ 29 сентября 2015

Вы можете просто вызвать метод onCreate. Если хотите, можете вызвать методы onStart и onResume.

onCreate(null);

Я решил эту проблему таким образом.

1 голос
/ 25 февраля 2013

После борьбы с этим в течение дня я понял это.
Это для нескольких уровней предпочтений.

parent - это экран предпочтений, в котором хранятся настройки, которые вы пытаетесьдля обновления.

Поскольку экран настроек отображается в виде диалогового окна, вы можете получить список из диалогового окна, а затем сообщить его адаптеру для обновления child .

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();

Я нашел R.id.list недоступен на старых телефонах, но это работает

    ListAdapter adapter = parent.getRootAdapter();
    if (adapter instanceof BaseAdapter) {
        ((BaseAdapter)adapter).notifyDataSetChanged();
    }
0 голосов
/ 11 июня 2018

После того, как вы внесете изменения в sharedPreferences, я думаю, вам следует просто вызвать invalidateHeaders () .Документы об этом:

Звоните, когда вам нужно изменить отображаемые заголовки.Это приведет к тому, что onBuildHeaders () позже будет вызываться для получения нового списка.

Это должно обновить интерфейс пользователя, чтобы показать новые значения.

0 голосов
/ 29 апреля 2016

Мне удалось написать метод, который на самом деле довольно прост и не требует аннулирования ListViews или какой-либо другой ситуации.Этот метод выполняет вызов к public ViewGroup removeView(View view), View requestLayout(), View forceLayout(), ViewGroup addView(View view) и, наконец, к вызову Fragment OnCreate(Bundle savedInstanceState) методов с несколькими нулевыми проверками и временной переменной final View для сохранения фактического представления, когдапредставление удалено.

Этот метод все еще довольно новый, и я буду давать ему некоторые настройки и уточнения в течение следующих 2 дней, но он работает без сбоев, как и без побочных эффектов.Так как класс, который я написал с кодом, изменяет фактический заголовок предпочтения и стили текста сводки для всего раздела (в этом и заключался весь смысл добавленных мной опций), я также добавил открытый конструктор классов, которыедействия, которые находятся в стеке действий под экраном стиля предпочтений, поэтому их можно обновлять одновременно.Скорее всего, я перенесу этот новый метод в класс представлений frameworks, чтобы его можно было сделать доступным для всей системы.

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) {
    }
}

Сами переменные представления изначально устанавливаются при инициализации класса и инициализируются и определяются вView onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) и View onViewCreated(View view, Bundle savedInstanceState).Сами переменные представления устанавливаются изначально в инициализации класса.

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;
}

В действиях в стеке ниже, в моем классе PreferenceStyle, я установил пустой конструктор, который можно инициализировать в любом месте приложения.

public class DEMENTED extends SettingsPreferenceFragment implements
        Preference.OnPreferenceChangeListener, View.OnClickListener {

    public DEMENTED() {
         super();
    }

    //other code to do whatever here

В моем классе PreferenceStyle я импортировал свой класс DEMENTED, затем установил его как переменную до onCreate(Bundle savedInstanceState):

private DEMENTED mDemented;

Затем инициализировал переменную в onCreate(Bundle savedInstanceState):

mDemented = new DEMENTED();

Вызов моему классу DEMENTED для перезагрузки его представления выполняется в моем методе reloadView(View view), но представление переменной, используемое для вызова, является переменной View, установленной непосредственно перед вызовом и устанавливаемой как null:

View tmp = null;
mDemented.reLoadView(tmp);

и мой класс DEMENTED проверяет, является ли включенный View в вызове метода нулевым, и если да, устанавливает его в локализованную переменную View, чтобы метод мог выполнять свою работу с локальными переменными:

public void reLoadView(View view) {
    if (view == null) {
        view = mView;
        Log.i(TAG, "The current View is: " + view);
    }
    //all the other good stuff here

В основном, это использует ViewGroup, как определено в onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState):

    mViewGroup = parent;

, а переменная View установлена ​​в onViewCreated(View view, Bundle savedInstanceState)

    mView = view;

Надеюсь, это кому-то поможетпотому что это был вопрос, который я неоднократно повторял здесь, и мне еще предстоит найти надежное решение практически везде, где бы не использовалось несколько классов, используемых в качестве утилит.Если у кого-либо есть предложения по упрощению комментариев или что-либо еще, не стесняйтесь комментировать.

0 голосов
/ 15 марта 2016

Этот класс указывает на простой экран настроек. Который может вам помочь.

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 голосов
/ 19 января 2014

Если вы ориентируетесь на API 11 и выше, вы можете использовать invalidateHeaders.

Из документов:

Позвоните, когда вам нужно изменить отображаемые заголовки.Это приведет к тому, что onBuildHeaders () позже будет вызван для получения нового списка.

...