How to move back from Preferences subscreen to main screen in PreferenceFragmentCompat?

前端 未结 2 756
礼貌的吻别
礼貌的吻别 2020-12-30 08:15

I am trying to implement a Settings screen using PreferenceFragmentCompat. My preference xml has a preference subscreen like this:

preferences.xml

相关标签:
2条回答
  • 2020-12-30 08:29

    By using setPreferenceScreen you are setting the root preference screen to the sub preference screen which is preventing you from having a hierarchy of preference screens to navigate back through.

    I suggest that you treat each PreferenceScreen as a Fragment and add a new Fragment when you navigate into a sub screen.

    @Override
    public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat,
                                           PreferenceScreen preferenceScreen) {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        MyPreferenceFragment fragment = new MyPreferenceFragment();
        Bundle args = new Bundle();
        args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.getKey());
        fragment.setArguments(args);
        ft.add(R.id.fragment_container, fragment, preferenceScreen.getKey());
        ft.addToBackStack(preferenceScreen.getKey());
        ft.commit();
        return true;
    }
    

    MyPreferenceFragment

    public class MyPreferenceFragment extends AppPreferenceFragment {
    
       public static final String FRAGMENT_TAG = "my_preference_fragment";
    
       public MyPreferenceFragment() {
       }
    
       @Override
       public void onCreatePreferences(Bundle bundle, String rootKey) {
           setPreferencesFromResource(R.xml.preferences, rootKey);
       }
    }
    

    AppPreferenceFragment

    public abstract class AppPreferenceFragment extends PreferenceFragmentCompat {
    
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    
        // Set the default white background in the view so as to avoid transparency
          view.setBackgroundColor(
                  ContextCompat.getColor(getContext(), R.color.background_material_light));
    
      }
    }
    

    That way when you press the back button each Fragment will be popped from the stack.

    For more information see this GitHub project

    0 讨论(0)
  • 2020-12-30 08:40

    I have added a complete working example with screenshots and code snippets here in this post, I hope this will be helpful to someone.

    It covers following scenarios:-- 1) A main setting screen with two checkboxes and a subscreen title. 2) On click of subscreen title, the new preference subscreen opens. 3) On back pressed, the control goes to main Settings screen. So the back press is handled properly.

    The MainActivity looks like this(overridden onPreferenceStartScreen method handles the opening of new subscreen in a new window):--

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

    and finally the in subscreen fragment setPreferencesFromResource(R.xml.preferences, rootKey); handles the attachment of subscreen to the rootkey.

    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)
提交回复
热议问题