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

Подэкран Preference не открывается при использовании support.v7.preference

Я пытаюсь реализовать настройки с субэкранами, используя AppCompatActivity и support.v7.preference

В соответствии с документами каждый PreferenceScreen в другом PreferenceScreen функционирует как вспомогательный экран, и структура будет обрабатывать отображение его при нажатии. http://developer.android.com/guide/topics/ui/settings.html#Subscreens

<PreferenceScreen  xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- opens a subscreen of settings -->
    <PreferenceScreen
        android:key="button_voicemail_category_key"
        android:title="@string/voicemail"
        android:persistent="false">
        <ListPreference
            android:key="button_voicemail_provider_key"
            android:title="@string/voicemail_provider" ... />
        <!-- opens another nested subscreen -->
        <PreferenceScreen
            android:key="button_voicemail_setting_key"
            android:title="@string/voicemail_settings"
            android:persistent="false">
            ...
        </PreferenceScreen>
        <RingtonePreference
            android:key="button_voicemail_ringtone_key"
            android:title="@string/voicemail_ringtone_title"
            android:ringtoneType="notification" ... />
        ...
    </PreferenceScreen>
    ...
</PreferenceScreen>

Это работает отлично, используя native Activity, PreferenceFragment... но используя AppCompatActivity и PreferenceFragmentCompat, щелчок по элементу Preference просто выделяет его, но не открывает подэкран.

Я ничего не смог найти в этом чтении документов и кода... мне нужно реализовать любые дополнительные обратные вызовы?


EDIT: только для полноты...

Это работает и открывает вспомогательный экран:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState == null) {
            getFragmentManager().beginTransaction()
                    .replace(android.R.id.content, new DemoPreferenceFragment())
                    .commit();
        }
    }

    static public class DemoPreferenceFragment extends PreferenceFragment {

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.preferences);
        }
    }
}

Это не работает/открывает дополнительный экран:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .replace(android.R.id.content, new DemoPreferenceFragment())
                    .commit();
        }
    }

    static public class DemoPreferenceFragment extends PreferenceFragmentCompat {

        @Override
        public void onCreatePreferences(Bundle bundle, String s) {
            addPreferencesFromResource(R.xml.preferences);
        }
    }
}

Изменить: 25/01/2016

После того, как я провел несколько дней с поддержкой support.v7.preference, я подытожил свои выводы здесь, надеясь, что это может помочь другим: HowTo использовать support.v7.preference с AppCompat и потенциальными недостатками

4b9b3361

Ответ 1

Он выглядит как ошибка в PreferenceFragmentCompat или недостаточность документов. Он имеет метод onNavigateToScreen, который вызывается, когда вы нажимаете элемент PreferenceScreen.

Но метод getCallbackFragment() возвращает значение null по умолчанию, поэтому вам нужно переопределить его в своем фрагменте, чтобы вернуть его. Также вам нужно реализовать PreferenceFragmentCompat.OnPreferenceStartScreenCallback.

public class SettingsFragment extends PreferenceFragmentCompat implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback {

    public static SettingsFragment newInstance() {
        return new SettingsFragment();
    }

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        addPreferencesFromResource(R.xml.news_settings);
    }

    @Override
    public Fragment getCallbackFragment() {
        return this;
    }

    @Override
    public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat, PreferenceScreen preferenceScreen) {
        preferenceFragmentCompat.setPreferenceScreen(preferenceScreen);
        return true;
    }
}

Но это приводит к другой проблеме, когда вы не можете вернуться к исходному экрану PreferenceScreen,

Другой способ - заменить фрагмент, описанный здесь Как вернуться из основного экрана Preferences на главный экран в PreferenceFragmentCompat?

Ответ 2

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

Я следил за этой проблемой в Android-трекере с открытым исходным кодом - здесь

В официальной документации отсутствует документация по загрузке предпочтения subscreen- См. официальную документацию - -

Основной экран расширенных настроек как 2 флажка и отключенный заголовок подэкрана (пользовательские настройки шаблона): -

подэкранный заголовок отключен

Как только мы установим флажок "Пользовательский", заголовок субэкрана будет включен. заголовок подэкрана включен

При щелчке по настройкам пользовательского шаблона подэкран открывается на новом экране

введите здесь описание изображения

Вот пример кода с документацией: -

В файле res/xml/preferences.xml: -

    <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    android:summary="Trying intro text">
    <PreferenceCategory android:title="Settings">
        <CheckBoxPreference
            android:defaultValue="true"
            android:key="defaultPress"
            android:title="Default settings" />
        <CheckBoxPreference
            android:defaultValue="false"
            android:key="customKey"
            android:title="Custom" />
        <PreferenceScreen
            android:key="customPrefKey"
            android:title="Custom Pattern Settings">
            <PreferenceCategory
                android:key="customSettingsKey"
                android:title="Custom Settings">
                <ListPreference
                    android:defaultValue="4"
                    android:entries="@array/initialClickArray"
                    android:entryValues="@array/initialClickValues"
                    android:key="initialClicks"
                    android:summary="initialClicksSummary"
                    android:title="No. Of Clicks" />
                <ListPreference
                    android:defaultValue="5"
                    android:entries="@array/initialTimeArray"
                    android:entryValues="@array/initialTimeValues"
                    android:key="initialTimeKey"
                    android:summary="Time to complete clicks"
                    android:title="Time to complete" />
            </PreferenceCategory>
        </PreferenceScreen>
    </PreferenceCategory>
</PreferenceScreen>

MainActivity.java должен реализовать интерфейс PreferenceFragmentCompat.OnPreferenceStartScreenCallback, а затем переопределить метод - onPreferenceStartScreen

public class MainActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback {

    private static final String TAG = MainActivity.class.getName();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment fragment = null;
        if (savedInstanceState == null) {
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragment = new AdvancedSettingsFragment().newInstance("Advanced Setting");
            fragmentTransaction.add(R.id.fragment_container, fragment);
            fragmentTransaction.commit();
        }
    }

    @Override
        public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat,
                                           PreferenceScreen preferenceScreen) {
        Log.d(TAG, "callback called to attach the preference sub screen");
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        AdvancedSettingsSubScreenFragment fragment = AdvancedSettingsSubScreenFragment.newInstance("Advanced Settings Subscreen");
        Bundle args = new Bundle();
        //Defining the sub screen as new root for the  subscreen
        args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.getKey());
        fragment.setArguments(args);
        ft.replace(R.id.fragment_container, fragment, preferenceScreen.getKey());
        ft.addToBackStack(null);
        ft.commit();
        return true;
    }

Для главного экрана настроек (фрагмент): -

public class AdvancedSettingsFragment extends PreferenceFragmentCompat {
    private static final String TAG = AdvancedSettingsFragment.class.getName();
    public static final String PAGE_ID = "page_id";

    public static AdvancedSettingsFragment newInstance(String pageId) {
        AdvancedSettingsFragment f = new AdvancedSettingsFragment();
        Bundle args = new Bundle();
        args.putString(PAGE_ID, pageId);
        f.setArguments(args);
        return (f);
    }

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.preferences);
        final CheckBoxPreference customPreference = (CheckBoxPreference) findPreference("customKey");
        final Preference customSettings = (Preference) findPreference("customPrefKey");
        // First time loading the preference screen, we check the saved settings and enable/disable the custom settings, based on the custom check box
        //get the customSettings value from shared preferences
        if (getCustomSettings(getActivity())) {
            customPreference.setChecked(true);
            customSettings.setEnabled(true);
        } else {
            customPreference.setChecked(false);
            customSettings.setEnabled(false);
        }
        customPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object selectedValue) {
                Log.d(TAG, "Inside on preference change of custom checkbox selection " + selectedValue.getClass());
                if ((Boolean) selectedValue) {
                    customSettings.setEnabled(true);
                }else{
                    customSettings.setEnabled(false);
                }
                return true;
            }
        });
    }
    private boolean getCustomSettings(Context context) {
        return PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean("customKey", false);
    }
}

и, наконец, для загрузки подэкрана:

public class AdvancedSettingsSubScreenFragment extends PreferenceFragmentCompat {
    private static final String TAG = AdvancedSettingsSubScreenFragment.class.getName();
    public static final String PAGE_ID = "page_id";

    public static AdvancedSettingsSubScreenFragment newInstance(String pageId) {
        AdvancedSettingsSubScreenFragment f = new AdvancedSettingsSubScreenFragment();
        Bundle args = new Bundle();
        args.putString(PAGE_ID, pageId);
        f.setArguments(args);
        return (f);
    }

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        // rootKey is the name of preference sub screen key name , here--customPrefKey
        setPreferencesFromResource(R.xml.preferences, rootKey);
        Log.d(TAG, "onCreatePreferences of the sub screen " + rootKey);
    }
}

Ответ 3

Одна чрезвычайно важная вещь, которую вам нужно запомнить:

Ваш экран предпочтений должен содержать:

android:key="name_a_unique_key"

В противном случае это не сработает. Я провел несколько часов с

Ответ 4

Переопределение PreferenceFragmentCompat.OnPreferenceStartScreenCallback

и добавив следующее к моему фрагменту предпочтений, сохраненному моим днем ​​

@Override
public Fragment getCallbackFragment() {
    return this;
}

@Override
public boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref) {
    caller.setPreferenceScreen(pref);
    return true;
}

Моя версия предпочтения

compile 'com.android.support:preference-v7:25.0.0'