Подтвердить что ты не робот

Как обновить 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.";
}
4b9b3361

Ответ 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() позже вызывается для извлечения нового списка.