FragmentContainerView 使用 findNavController
FragmentContainerView using findNavController
我正在使用带底部导航的 Android 导航组件,lint 会发出有关用 <FragmentContainerView>
替换 <fragment>
标签的警告,但是当我替换时,findNavController
是不工作它给了我关于它没有设置 NavController 的错误
片段
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/mobile_navigation" />
Activity
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_classes, R.id.navigation_schedule, R.id.navigation_settings
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
根据 this issue,当使用 FragmentContainerView
时,您需要使用 findFragmentById()
找到 NavController
而不是在 [=16] 中使用 findNavController()
=]:
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
这是因为 findNavController(R.id.nav_host_fragment)
依赖于已经创建的片段视图,而使用 FragmentContainerView
时则不是这种情况(因为它在幕后使用 FragmentTransaction
添加NavHostFragment
).
如果您使用的是Fragment 1.4.0 or higher and View Binding, you can simply this considerably by using the getFragment()
方法:
val navController = binding.container.getFragment<NavHostFragment>().navController
在接受的答案之上,可以使用的一个小快捷方式是:
supportFragmentManager.findFragmentById(R.id.navHostMain)?.findNavController()
此致
替换此行:
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
与
NavController navController = getNavController();
其中 getNavController()
看起来像这样:
// workaround for https://issuetracker.google.com/issues/142847973
@NonNull
private NavController getNavController() {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
if (!(fragment instanceof NavHostFragment)) {
throw new IllegalStateException("Activity " + this
+ " does not have a NavHostFragment");
}
return ((NavHostFragment) fragment).getNavController();
}
@friederbluemle 的回答有一个更简单的方法。
断言检查就足够了。
NavHostFragment navHostFragment
= (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
assert navHostFragment != null : "navHostFragment not found";
NavController navController = navHostFragment.getNavController();
在你的build.gradle (Module: App)这一行添加
implementation "androidx.navigation:navigation-fragment-ktx:2.3.2"
并在 activity
中使用它
val navController = supportFragmentManager.findFragmentById(R.id.your_id_nav_host_fragment)
?.findNavController()
在片段中
val navController = findNavController()
我用扩展解决了我的问题:
fun FragmentActivity.findFragmentContainerNavController(@IdRes host: Int):NavController {
try {
val navHostFragment = supportFragmentManager.findFragmentById(host) as NavHostFragment
return navHostFragment.findNavController()
} catch (e: Exception) {
throw IllegalStateException("Activity $this does not have a NavController set on $host")
}
}
这是简单的答案 -
val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragmentContainerView)
作为 NavHostFragment
val navController = navHostFragment.navControllermenus.setupWithNavController(navController)
使用简单的 <fragment>
标签代替 <androidx.fragment.app.FragmentContainerView>
我正在使用带底部导航的 Android 导航组件,lint 会发出有关用 <FragmentContainerView>
替换 <fragment>
标签的警告,但是当我替换时,findNavController
是不工作它给了我关于它没有设置 NavController 的错误
片段
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/mobile_navigation" />
Activity
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_classes, R.id.navigation_schedule, R.id.navigation_settings
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
根据 this issue,当使用 FragmentContainerView
时,您需要使用 findFragmentById()
找到 NavController
而不是在 [=16] 中使用 findNavController()
=]:
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
这是因为 findNavController(R.id.nav_host_fragment)
依赖于已经创建的片段视图,而使用 FragmentContainerView
时则不是这种情况(因为它在幕后使用 FragmentTransaction
添加NavHostFragment
).
如果您使用的是Fragment 1.4.0 or higher and View Binding, you can simply this considerably by using the getFragment()
方法:
val navController = binding.container.getFragment<NavHostFragment>().navController
在接受的答案之上,可以使用的一个小快捷方式是:
supportFragmentManager.findFragmentById(R.id.navHostMain)?.findNavController()
此致
替换此行:
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
与
NavController navController = getNavController();
其中 getNavController()
看起来像这样:
// workaround for https://issuetracker.google.com/issues/142847973
@NonNull
private NavController getNavController() {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
if (!(fragment instanceof NavHostFragment)) {
throw new IllegalStateException("Activity " + this
+ " does not have a NavHostFragment");
}
return ((NavHostFragment) fragment).getNavController();
}
@friederbluemle 的回答有一个更简单的方法。 断言检查就足够了。
NavHostFragment navHostFragment
= (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
assert navHostFragment != null : "navHostFragment not found";
NavController navController = navHostFragment.getNavController();
在你的build.gradle (Module: App)这一行添加
implementation "androidx.navigation:navigation-fragment-ktx:2.3.2"
并在 activity
中使用它val navController = supportFragmentManager.findFragmentById(R.id.your_id_nav_host_fragment)
?.findNavController()
在片段中
val navController = findNavController()
我用扩展解决了我的问题:
fun FragmentActivity.findFragmentContainerNavController(@IdRes host: Int):NavController {
try {
val navHostFragment = supportFragmentManager.findFragmentById(host) as NavHostFragment
return navHostFragment.findNavController()
} catch (e: Exception) {
throw IllegalStateException("Activity $this does not have a NavController set on $host")
}
}
这是简单的答案 -
val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragmentContainerView)
作为 NavHostFragment
val navController = navHostFragment.navControllermenus.setupWithNavController(navController)
使用简单的 <fragment>
标签代替 <androidx.fragment.app.FragmentContainerView>