Как обновить 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.";
}
Ответы
Ответ 1
Николай ответил правильно. Я просто хочу добавить здесь код, чтобы более четко проиллюстрировать его точку зрения.
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
в его нормальном жизненном цикле.
Ответ 2
Вместо
finish();
startActivity(getIntent());
Я предпочитаю следующий код:
setPreferenceScreen(null);
addPreferencesFromResource(R.xml.preferences);
Это будет reset отображение, но без всей процедуры завершения и ее последствий.
Плюс этот код хорошо работает с PreferenceActivity
и PreferenceFragment
.
Это интересно, если вы хотите динамически изменить значение языкового стандарта, например. В этом случае работать с менеджером недостаточно, потому что вам нужна полная перезагрузка названий и значений.
EDIT: setPreferenceScreen
устарел в PreferenceActivity
(все еще работает), но не находится в PreferenceFragment
Ответ 3
Существует простой способ обновить все элементы в списке сразу. Просто выполните следующие действия:
getPreferenceScreen().removeAll();
addPreferencesFromResource(R.xml.preferences);
При таком подходе вы не потеряете позицию ListView.
Ответ 4
Внесите onPreferenceChange
и переключите связанные с ним функции. Чтобы "обновить" всю активность, вам нужно finish()
и перезапустить ее.
Ответ 5
После борьбы с этим в течение дня я понял это.
Это для нескольких уровней предпочтений.
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();
}
Ответ 6
Вы можете просто вызвать метод WithCreate. Если вы хотите, вы можете вызвать методы onStart и onResume.
onCreate(null);
Я решил свою проблему таким образом.
Ответ 7
Этот класс указывает простой экран предпочтений. Что может вам помочь.
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);
}
}
Ответ 8
Мне удалось написать метод, который на самом деле прост и без необходимости отменять ListViews или, что бы там ни было. Этот метод вызывает вызов public ViewGroup removeView(View view)
, View requestLayout()
, View forceLayout()
, ViewGroup addView(View view)
и, наконец, вызов методов Fragment OnCreate(Bundle savedInstanceState)
с несколькими проверками null и временной переменной 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)
, но представление переменной, используемое для вызова, представляет собой переменную вида, установленную непосредственно перед вызовом, и устанавливается как null:
View tmp = null;
mDemented.reLoadView(tmp);
и мой класс DEMENTED проверяет, является ли включенное представление в вызове метода нулевым, и если он устанавливает его в локализованную переменную 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;
Надеюсь, это поможет кому-то, потому что это вопрос, который я неоднократно повторял здесь, и мне еще предстоит найти надежное решение в любом месте, где не было нескольких классов, используемых как utils. Если у кого-то есть предложения по комментариям, чтобы упростить или что-либо не стесняться комментировать.
Ответ 9
После того, как вы передадите изменения в sharedPreferences, я думаю, что вы должны просто вызвать invalidateHeaders(). Документы об этом:
Звоните, когда вам нужно изменить отображаемые заголовки. Это приведет к тому, что onBuildHeaders() позже будет вызван для получения нового списка.
Ответ 10
Другой подход к решению, если вы используете действие, которое содержит PreferenceFragmentCompat
Здесь я создаю действие, которое содержит фрагмент с группой элементов предпочтений, накачанных из settings_main.xml; PreferenceActivity имеет меню параметров, которое содержит элемент для сброса параметров предпочтения по умолчанию.
1. res/xml/settings_main.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ListPreference
android:defaultValue="@string/settings_list_default"
android:entries="@array/settings_list_labels"
android:entryValues="@array/settings_list_values"
android:key="@string/settings_list_key"
android:title="@string/settings_list_title"/>
<EditTextPreference
android:defaultValue="@string/settings_edit_text_default"
android:inputType="text"
android:key="@string/setting_edit_text_key"
android:selectAllOnFocus="true"
android:title="@string/settings_edit_text_title"/>
</PreferenceScreen>
2. layout_activity.xml layout
<?xml version="1.0" encoding="utf-8"?
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/settings_fragment"
android:name="com.example.android.myapp.SettingsActivity$MyPreferenceFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.myapp.SettingsActivity" />
3. НастройкаActive & MyPreferenceFragment
public class SettingsActivity extends AppCompatActivity {
MyPreferenceFragment mMyPreferenceFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
}
@Override
protected void onResume() {
super.onResume();
mMyPreferenceFragment = (MyPreferenceFragment) getSupportFragmentManager().findFragmentById(R.id.settings_fragment);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar
getMenuInflater().inflate(R.menu.menu_settings, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handling action bar item clicks
switch (item.getItemId()) {
case R.id.menu_reset:
mMyPreferenceFragment.resetPreferenceToDefault();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public static class MyPreferenceFragment
extends PreferenceFragmentCompat
implements Preference.OnPreferenceChangeListener /* listen to when the user updates the preferences and
update the preference summary with the change.*/ {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onCreatePreferences(Bundle bundle, String s) {
addPreferencesFromResource(R.xml.settings_main); // inflates the Preference XML file
inflatePreferenceViews();
}
public void inflatePreferenceViews() {
// update the preference summary (the UI) when the settings activity is created
Preference list = findPreference(getString(R.string.settings_list_key));
bindPreferenceToSettingActivity(list, getString(R.string.settings_list_default));
Preference editText = findPreference(getString(R.string.setting_edit_text_key));
bindPreferenceToSettingActivity(editText, getString(R.string.settings_edit_text_default));
}
private void bindPreferenceToSettingActivity(Preference preference, String defaultValue) {
// set the current MyPreferenceFragment instance to listen to changes to the preference we pass
preference.setOnPreferenceChangeListener(this);
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(preference.getContext());
String preferenceString = preferences.getString(preference.getKey(), defaultValue); // read the current value of the preference stored in the SharedPreferences on the device, and display that in the preference summary
onPreferenceChange(preference, preferenceString);
}
@Override
// this method will be called when a preference has been changed
// returns "true" to update the state of the Preference with the new value on the UI
public boolean onPreferenceChange(Preference preference, Object value) {
String newValue = value.toString();
// update the onPreferenceChange() method in EarthquakePreferenceFragmet to properly update
// the summary of a ListPreference (using the label, instead of the key)
if (preference instanceof ListPreference) {
ListPreference listPreference = (ListPreference) preference;
int prefIndex = listPreference.findIndexOfValue(newValue);
if (prefIndex >= 0) {
CharSequence[] labels = listPreference.getEntries();
preference.setSummary(labels[prefIndex]);
}
} else { // For other preferences like EditTextPreference in our example
preference.setSummary(newValue);
}
return true;
}
private void resetPreferenceToDefault(){
Preference prefList = findPreference(getString(R.string.settings_list_key));
Preference prefEditText = findPreference(getString(R.string.setting_edit_text_key));
onPreferenceChange(prefList, getString(R.string.settings_list_default));
onPreferenceChange(prefEditText, getString(R.string.settings_edit_text_default));
}
}
}
Ответ 11
Если вы настроили таргетинг на API 11 и выше, вы можете использовать invalidateHeaders
.
Из документов:
Вызов, когда вам нужно изменить отображаемые заголовки. Приведет к в onBuildHeaders() позже вызывается для извлечения нового списка.