我们可以使用带有设置首选项的 Android Jetpack 导航组件吗?

Mer*_*aju 11 android android-preferences kotlin android-jetpack-navigation

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

Car*_*rel 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>
Run Code Online (Sandbox Code Playgroud)

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

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

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
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

然而,有一个小 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) }
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

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