Как обновить PreferenceActivity, чтобы показать изменения в настройках?

основываясь на следующем коде, можете ли вы рассказать мне, как обновить окно PreferenceActivity, чтобы сразу показать изменения в настройках? Например: пользователь нажимает переключатель master chime на 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 ответов


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

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 в своем нормальном жизненном цикле.


вместо

finish();
startActivity(getIntent());

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

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

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

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

EDIT:setPreferenceScreen осуждается в PreferenceActivity (все еще работает), но не в PreferenceFragment


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

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

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


реализовать onPreferenceChange и переключать связанные perfs оттуда. Чтобы "обновить" всю активность, вам нужно finish() и перезапустить его.


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

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

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

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

Я нашел ИД Р..список не доступен на старых телефонах, но это работает

    ListAdapter adapter = parent.getRootAdapter();
    if (adapter instanceof BaseAdapter) {
        ((BaseAdapter)adapter).notifyDataSetChanged();
    }

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

onCreate(null);

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


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

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

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

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

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 класс I импортировал мой сумасшедший класс, а затем установил его как переменную до onCreate(Bundle savedInstanceState):

private DEMENTED mDemented;

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

mDemented = new DEMENTED();

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

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

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

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;

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

    mView = view;

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


после фиксации изменений в sharedPreferences, я думаю, вы должны просто позвонить invalidateHeaders .


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

документы:

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