如何使用 Jetpack Navigation 从嵌套片段导航到父片段?
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$$special$$inlined$button$lambda.onClick(RegistrationSecurityFragment.kt:106)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access00(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)
在您的代码中,您可以将全局操作的资源 ID 传递给每个 UI 元素的 navigate()
方法。
your_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Navigation.findNavController(view).navigate(R.id.main_fragment);
}
});
如果您有多个导航图,请确保您使用的是正确的导航控制器。在某些情况下使用 Navigation.findNavController(view) 您可能需要获取根视图才能获得根的导航。希望,这会有所帮助。
感谢@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))
}
当您有 嵌套 个 NavController 时,findNavController()
return 仅在最后一个。要获取以前的 navController,您可以使用 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)
我有主导航: 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$$special$$inlined$button$lambda.onClick(RegistrationSecurityFragment.kt:106)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access00(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)
在您的代码中,您可以将全局操作的资源 ID 传递给每个 UI 元素的 navigate()
方法。
your_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Navigation.findNavController(view).navigate(R.id.main_fragment);
}
});
如果您有多个导航图,请确保您使用的是正确的导航控制器。在某些情况下使用 Navigation.findNavController(view) 您可能需要获取根视图才能获得根的导航。希望,这会有所帮助。
感谢@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))
}
当您有 嵌套 个 NavController 时,findNavController()
return 仅在最后一个。要获取以前的 navController,您可以使用 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)