繁体   English   中英

如何使用 Jetpack Navigation 从嵌套 Fragment 导航到父 Fragment?

[英]How to navigate from nested Fragment to parent fragment using Jetpack Navigation?

我有主导航:SplashFragment -> RegistrationFragment -> RootFragment

<fragment
    android:id="@+id/splashFragment"
    android:name="com.low6.low6.features.splash.SplashFragment"
    android:label="Splash"
    tools:layout="@layout/fragment_splash" >
    <action
        android:id="@+id/action_next"
        app:clearTask="true"
        app:destination="@id/registrationFragment" />
</fragment>

<fragment
    android:id="@+id/registrationFragment"
    android:name="com.low6.low6.features.registration.RegistrationFragment"
    android:label="Register">
    <action
        android:id="@+id/action_next"
        app:clearTask="true"
        app:destination="@id/rootFragment" />
</fragment>

<fragment
    android:id="@+id/rootFragment"
    android:name="com.low6.low6.core.RootFragment"
    android:label="@string/home"
    tools:layout="@layout/fragment_root" />

而且我嵌套了注册导航:RegistrationPersonalFragment -> RegistrationContactFragment -> RegistrationSecurityFragment

<fragment
    android:id="@+id/registrationPersonalFragment"
    android:name="com.low6.low6.features.registration.RegistrationPersonalFragment"
    android:label="Register">

    <action
        android:id="@+id/action_next"
        app:destination="@+id/registrationContactFragment" />
</fragment>

<fragment
    android:id="@+id/registrationContactFragment"
    android:name="com.low6.low6.features.registration.RegistrationContactFragment"
    android:label="Register">

    <action
        android:id="@+id/action_next"
        app:destination="@+id/registrationSecurityFragment" />
</fragment>

<fragment
    android:id="@+id/registrationSecurityFragment"
    android:name="com.low6.low6.features.registration.RegistrationSecurityFragment"
    android:label="Register">

    <action
        android:id="@+id/action_next"
        app:destination="@+id/rootFragment" />
</fragment>

如何使用 Jetpack Navigation 组件从最后一个嵌套的 RegistrationSecurityFragment 重定向到 RootFragment?

目前

<action
    android:id="@+id/action_next"
    app:destination="@+id/rootFragment" />

   navigateTo(R.id.action_next)

给我

    java.lang.IllegalArgumentException: navigation destination com.xxx:id/rootFragment referenced from action com.xxx:id/action_next is unknown to this NavController
    at androidx.navigation.NavController.navigate(NavController.java:691)
    at androidx.navigation.NavController.navigate(NavController.java:648)
    at androidx.navigation.NavController.navigate(NavController.java:634)
    at com.xxx.core.BaseFragment.navigateTo(BaseFragment.kt:73)
    at com.xxx.core.BaseFragment.navigateTo$default(BaseFragment.kt:66)
    at com.xxx.features.registration.RegistrationSecurityFragment$epoxyController$1$$special$$inlined$button$lambda$1.onClick(RegistrationSecurityFragment.kt:106)
    at android.view.View.performClick(View.java:6597)
    at android.view.View.performClickInternal(View.java:6574)
    at android.view.View.access$3100(View.java:778)
    at android.view.View$PerformClick.run(View.java:25885)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

如果您有多个导航图,请确保您使用的是正确的导航控制器。 在某些情况下,使用 Navigation.findNavController(view) 您可能需要获取根视图以获取根的导航。 希望,这会有所帮助。

当您嵌套了NavControllers 时, findNavController()只返回最后一个。 要获取以前的导航控制器,您可以使用parentFragment属性向上遍历。

这种方法的扩展:

// find all nav controllers from closest to farest
fun Fragment.findAllNavControllers(): List<NavController> {
    val navControllers = mutableListOf<NavController>()
    var parent = parentFragment
    while (parent != null) {
        if (parent is NavHostFragment) {
            navControllers.add(parent.navController)
        }
        parent = parent.parentFragment
    }
    return navControllers
}

// find one nav controller by fragment id
fun Fragment.findNavControllerById(@IdRes id: Int): NavController {
    var parent = parentFragment
    while (parent != null) {
        if (parent is NavHostFragment && parent.id == id) {
            return parent.navController
        }
        parent = parent.parentFragment
    }
    throw RuntimeException("NavController with specified id not found")
}

和用法:

findAllNavControllers()[2]
findNavControllerById(R.id.navHostFragment)

在您的代码中,您可以将全局操作的资源 ID 传递给每个 UI 元素的navigate()方法。

your_button.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
       Navigation.findNavController(view).navigate(R.id.main_fragment);
   }
});

感谢@Vladimir 的回答,我想出了这个解决方案

val mainNavView = requireActivity().findViewById<View>(R.id.mainNavFragment)
Navigation.findNavController(mainNavView).navigate(R.id.action_next)

你可以这样做;

在子片段中

// parentFragment = getParentFragment() for java
(parentFragment as MyParentFragment).myNavigationHandler(myArguments)

在父片段中

fun myNavigationHandler(myArguments) {
    Navigation.findNavController(binding.root)
        .navigate(MyFragmentDirections.actionMyAction(myArguments))
}
findNavController().navigate(HostFragmentDirections.actionHostToOtherFragment())

HostFragment 只是一个示例,它应该是嵌套片段的主机名称。 对于每个努力从嵌套片段导航到某个地方的人来说,这很有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM