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>