Preference sub-screen not opening when using support.v7.preference

前端 未结 5 672
青春惊慌失措
青春惊慌失措 2020-12-09 15:59

I am trying to implement preferences with sub-screens using AppCompatActivity and support.v7.preference

According to the docs, every PreferenceScreen within another

相关标签:
5条回答
  • 2020-12-09 16:04

    One extremely important thing you need you remember:

    Your PreferenceScreen must contain :

    android:key="name_a_unique_key"
    

    Otherwise, it will not work. I've spent hours with thí

    0 讨论(0)
  • 2020-12-09 16:09

    It looks like a bug in PreferenceFragmentCompat or insufficiency of docs. It has method onNavigateToScreen which is called when you click on PreferenceScreen item.

    But method getCallbackFragment() returns null by default, so you need override it in your fragment to return this. Also you need to implement 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;
        }
    }
    

    But it leads to another problem when you can't get back to your initial PreferenceScreen,

    Another way is to replace fragment which is described here How to move back from Preferences subscreen to main screen in PreferenceFragmentCompat?

    0 讨论(0)
  • 2020-12-09 16:17

    This is complete working example, I hope this will be helpful to someone.It covers opening the preference subscreen and moving back to main Settings screen.

    I followed this issue in Android open source issue tracker --here

    The official documentation is missing the documentation for loading preference subscreen—Refer here for official documentation--

    The main advanced settings screen has 2 checkboxes and a disabled subscreen title(custom Pattern Settings):-

    Once we check the Custom checkbox, the subscreen title is enabled.

    On click of Custom pattern settings, the subscreen opens in new screen

    Here is the example code with documentation:--

    In res/xml/preferences.xml file:--

        <?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 should implement interface PreferenceFragmentCompat.OnPreferenceStartScreenCallback and then override the method-- 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;
        }
    

    For the main Settings screen(fragment):-

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

    and finally for the loading of subscreen:

    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);
        }
    }
    
    0 讨论(0)
  • 2020-12-09 16:24

    Overriding PreferenceFragmentCompat.OnPreferenceStartScreenCallback

    and adding the following to my preference fragment saved my day

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

    My preference version is

    compile 'com.android.support:preference-v7:25.0.0'
    
    0 讨论(0)
  • 2020-12-09 16:29

    It seems Google finally decides to support this in the newly released AndroidX preference 1.1.0-alpha.

    This video from Android Dev Summit covers something about preference sub screen.

    0 讨论(0)
提交回复
热议问题