【问题标题】:How to move back from Preferences subscreen to main screen in PreferenceFragmentCompat?如何从 Preferences 子屏幕移回 PreferenceFragmentCompat 中的主屏幕?
【发布时间】:2016-03-21 07:26:55
【问题描述】:

我正在尝试使用 PreferenceFragmentCompat 实现设置屏幕。我的偏好 xml 有一个像这样的偏好子屏幕:

preferences.xml

    <CheckBoxPreference
        android:defaultValue="false"
        android:key="@string/pref_sound_key"
        android:summary="@string/pref_sound_summary"
        android:title="@string/pref_sound_title" />

    <PreferenceScreen android:title="Inner Screen">
        <CheckBoxPreference
            android:defaultValue="true"
            android:key="@string/key_1"
            android:title="@string/title_1" />

        <CheckBoxPreference
            android:defaultValue="true"
            android:key="@string/key_1"
            android:title="@string/title_1" />

        <CheckBoxPreference
            android:defaultValue="true"
            android:key="@string/key_2"
            android:title="@string/title_2" />

        <CheckBoxPreference
            android:defaultValue="true"
            android:key="@string/key_3"
            android:title="@string/title_3" />
    </PreferenceScreen>

</PreferenceScreen>

Preference Main Screen

现在,在应用程序中,子屏幕不会打开,直到我在父活动中实现 PreferenceFragmentCompat.OnPreferenceStartScreenCallback 接口,如 PreferenceFragmentCompat 文档中指定的那样。

MainActivity.java

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

这就是问题所在。在实现界面时,子屏幕打开,但是我找不到回到第一个屏幕的方法。

Preference Subscreen

按返回键关闭应用程序。

有什么办法可以在应用栏上放一个后退箭头,这样按下它就会回到主屏幕?

【问题讨论】:

    标签: android preference-v7


    【解决方案1】:

    通过使用 setPreferenceScreen,您将根首选项屏幕设置为子首选项屏幕,这会阻止您有一个层次结构的首选项屏幕来导航。

    我建议您将每个 PreferenceScreen 视为一个 Fragment,并在您导航到子屏幕时添加一个新的 Fragment。

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

    这样,当你按下返回按钮时,每个 Fragment 都会从堆栈中弹出。

    有关更多信息,请参阅此GitHub 项目

    【讨论】:

    • 你能补充一下你的意思,因为每个 PreferenceScreen 都有一个片段。我应该定义两个偏好片段,一个用于主要设置,一个用于内部设置?我将如何实现这一目标?
    • @ArpitJaiswal 是的,每个 PreferenceScreen 需要一个 Fragment,但您可以通过为每个 PreferenceScreen 创建一个新实例并传入 PreferenceScreen 键来重复使用 MyPreferenceFragment。此键在 MyPreferenceFragment 中用于扩充您的首选项的 XML。我刚刚在我的答案中添加了一个 GitHub 链接,其中包含更多信息。
    • 这不处理使用主页按钮(操作/工具栏中的后退箭头,它只是关闭整个偏好活动。
    • MyPreferenceFragment 和 AppPreferenceFragment 是什么关系?
    • @StealthRabbi PreferenceFragments 默认具有透明背景,AppPreferenceFragment 是一个简单的基类,它将白色背景应用于扩展它的每个 Fragment。事后看来,可能有更好的方法可以达到同样的效果。
    【解决方案2】:

    我添加了一个完整的工作示例,带有屏幕截图和代码 sn-ps here in this post,希望这对某人有所帮助。

    它涵盖了以下场景:-- 1) 带有两个复选框和一个子屏幕标题的主设置屏幕。 2)点击子屏幕标题,新的偏好子屏幕打开。 3) 后按时,控制进入主设置屏幕。所以背压处理得当。

    MainActivity 看起来像这样(重写的 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;
        }
    

    最后是子屏幕片段setPreferencesFromResource(R.xml.preferences, 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);
        }
    }
    

    【讨论】:

    猜你喜欢
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-19
    • 1970-01-01
    相关资源
    最近更新 更多