代码之家  ›  专栏  ›  技术社区  ›  jakub

如何使用Jetpack导航从嵌套片段导航到父片段?

  •  2
  • jakub  · 技术社区  · 7 年前

    我有主导航: 飞溅碎片->注册片段->根碎片

    <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->登记担保碎片

    <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导航组件将上一个嵌套的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)
    
    3 回复  |  直到 6 年前
        1
  •  10
  •   Vladimir Gladun    7 年前

        2
  •  1
  •   karan    7 年前

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

    your_button.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View view) {
           Navigation.findNavController(view).navigate(R.id.main_fragment);
       }
    });
    
        3
  •  0
  •   jakub    7 年前

    多亏了@Vladimir answer,我想出了这个解决方案

    val mainNavView = requireActivity().findViewById<View>(R.id.mainNavFragment)
    Navigation.findNavController(mainNavView).navigate(R.id.action_next)
    
        4
  •  0
  •   lomec    6 年前

    你可以这样做;

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

    fun myNavigationHandler(myArguments) {
        Navigation.findNavController(binding.root)
            .navigate(MyFragmentDirections.actionMyAction(myArguments))
    }
    
        5
  •  0
  •   Pavel Shorokhov    5 年前

    当你有 导航控制器, 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)