12

是否可以使用 Android Jetpack 导航组件来导航设置首选项的片段?我有一个带有多个嵌套首选项片段的设置屏幕。我想知道使用 Android Jetpack 导航组件来完成我的任务是否可行?

4

2 回答 2

6

谷歌文档指出,偏好的分层嵌套现在已被弃用,有利于片段间导航;那就是现在的结构<PreferencesScreen> ... <PreferencesScreen ...> ... </PreferenceScreen> ... </PreferenceScreen>

文件建议<PreferenceScreen/>用首选项替换嵌套并设置app:fragment属性,因此

<xml ...>
<PreferencesScreen ...>
    <Preference
        android:title="Title"
        app:fragment="TLD.DOMAIN.PACKAGE.preferences.SUBPreferenceFragment"
        app:destination="@+id/SUBPreferenceFragment" # Not supported by Schema
        android:summary="Summary"/> 
</PreferenceScreen>

注意: 如果他们允许app:destination="@+id/SUBPreferenceFragment"识别导航目的地,那将非常方便;app:destination我只是从导航图的 XML 文件中复制。

从文档中,可以PREFERENCEFramgent通过引用 this 在 s之间导航preference.fragment,如下所示

class Activity : AppCompatActivity(),
                  // Preferences Interface
                  PreferenceFragmentCompat.OnPreferenceStartFragmentCallback
{
    ...
    override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, preference: Preference): Boolean 
    {
        // Instantiate the new Fragment
        val args = preference.extras
        val fragment = supportFragmentManager.fragmentFactory.instantiate(
            classLoader,
            preference.fragment)
        fragment.arguments = args
        fragment.setTargetFragment(caller, 0)
        // Replace the existing Fragment with the new Fragment
        supportFragmentManager.beginTransaction()
            .replace(R.id.FRAGMENT, fragment)
            .addToBackStack(null)
            .commit()
       return true
    }
    ...
}

然而,有一个小的 Snafoo !R.id.FRAGMENT在正常活动中表示活动视图中的占位符,在该占位符中,人们将交换不存在的主要片段。当使用 Navigation R.id.FRAGMENTmaps to时R.id.NAVIGATION,上面的代码用首选项交换了整个导航片段。对于使用导航的活动,需要重新制定。

class Activity : AppCompatActivity(),
                  // Preferences Interface
                  PreferenceFragmentCompat.OnPreferenceStartFragmentCallback
{
    ...
    override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, preference: Preference): Boolean {
        // Retrieve the navigation controller
        val navctrl = findNavController(R.id.navigation)
        // Identify the Navigation Destination
        val navDestination = navctrl.graph.find { target -> preference.fragment.endsWith(target.label?:"") } 
        // Navigate to the desired destination
        navDestination?.let { target -> navctrl.navigate(target.id) }
    }
    ...
}

虽然这可行,但我对决定navDestination. 如果您有更好的咒语,val navDestination = navctrl.graph.find { target -> preference.fragment.endsWith(target.label?:"") }请编辑问题或相应地发表评论,以便我更新答案。

于 2019-08-19T22:49:24.413 回答
1

是的,您可以在 Preference 片段中使用 Navigation 组件。

我还有一个包含多个嵌套片段的主要偏好片段。对我来说,最好的方法是在没有任何活动的情况下仅在偏好片段内部导航。所以我创建了 onPreferenceClickListeners 并像从普通片段中一样导航。

findPreference(getString(R.string.PREF_GN_BUTTON_MAIN)).setOnPreferenceClickListener(preference5 -> {
            Navigation.findNavController(requireView()).navigate(R.id.another_settings_fragment);
            return true;
        });

这种方式的好处是你可以使用 gradle 插件Safe args在目的地之间导航。因此,它比仅使用 id 更安全一些,就像Activity 中的Carel一样。

我试图覆盖onPreferenceStartFragment我的活动,但我看不到它的任何优势。我使用单活动架构。

于 2020-08-06T05:52:19.023 回答