Как обновить PreferenceActivity, чтобы показать изменения в настройках?
Основываясь на следующем коде, можете ли вы сказать мне, как обновить окно 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 ответов
Николай ответ правильный. Я просто хочу добавить код, чтобы проиллюстрировать его точку зрения более четко.
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
,
Это интересно, если вы хотите динамически изменить значение локали, например. В этом случае работы с менеджером недостаточно, поскольку требуется полная перезагрузка заголовков и значений.
РЕДАКТИРОВАТЬ: setPreferenceScreen
устарела в PreferenceActivity
(все еще работает), но не в PreferenceFragment
Есть простой способ обновить все элементы в списке одновременно. Просто сделайте следующее:
getPreferenceScreen().removeAll();
addPreferencesFromResource(R.xml.preferences);
При таком подходе вы не потеряете позицию ListView.
Вы можете просто вызвать метод onCreate. Если вы хотите, вы можете вызвать методы onStart и onResume.
onCreate(null);
Я решил свою проблему таким образом.
Воплощать в жизнь onPreferenceChange
и переключать связанные перфорации оттуда. Чтобы "освежить" всю активность, вам нужно finish()
и перезапустите его.
После борьбы с этим в течение дня, я понял это.
Это для нескольких уровней предпочтений.
parent - это экран настроек, который содержит настройки, которые вы пытаетесь обновить.
Поскольку экран настроек отображается в виде диалогового окна, вы можете получить список из диалогового окна, а затем сообщить его адаптеру для обновления дочернего элемента.
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();
}
Этот класс указывает на простой экран настроек. Который может вам помочь.
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)
методы с несколькими нулевыми проверками и 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, используемая для вызова, является переменной 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;
и переменная вида установлена в onViewCreated(View view, Bundle savedInstanceState)
mView = view;
Надеюсь, что это кому-то поможет, потому что этот вопрос я неоднократно повторял здесь, и мне еще не удалось найти надежного решения, где бы не использовалось несколько классов, используемых в качестве утилит. Если у кого-то есть комментарии, предложения по упрощению или что-либо не стесняйтесь комментировать.
После того, как вы внесете изменения в sharedPreferences, я думаю, что вы должны просто позвонить invalidateHeaders
,
Если вы ориентируетесь на API 11 и выше, вы можете использовать invalidateHeaders
,
Из документов:
Звоните, когда вам нужно изменить отображаемые заголовки. Это приведет к тому, что onBuildHeaders() позже будет вызван для получения нового списка.