android-fragments 使用findNavController的片段容器视图

iqjalb3h  于 2022-11-14  发布在  Android
关注(0)|答案(9)|浏览(200)

我正在使用带底部导航的Android导航组件,lint给出了一个关于将<fragment>标签替换为<FragmentContainerView>的警告,但当我替换时,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" />

活动

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)
}
r7knjye2

r7knjye21#

根据this issue,当使用FragmentContainerView时,需要使用findFragmentById()而不是在onCreate()中使用findNavController()来查找NavController

val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController

这是因为findNavController(R.id.nav_host_fragment)依赖于已经创建的Fragment视图,而使用FragmentContainerView时则不是这样(因为它使用了一个FragmentTransaction来添加NavHostFragment)。
如果您使用的是Fragment 1.4.0或更高版本以及View Binding,则可以通过使用getFragment()方法来大大简化此过程:

val navController = binding.container.getFragment<NavHostFragment>().navController
yiytaume

yiytaume2#

替换此行:

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();
    }
omtl5h9j

omtl5h9j3#

除了公认的答案之外,还有一个可以使用的小捷径:

supportFragmentManager.findFragmentById(R.id.navHostMain)?.findNavController()

此致

egdjgwm8

egdjgwm84#

添加到您的build.gradle(模块:App)这一行

implementation "androidx.navigation:navigation-fragment-ktx:2.3.2"

并在活动中使用

val navController = supportFragmentManager.findFragmentById(R.id.your_id_nav_host_fragment)
            ?.findNavController()

和碎片

val navController = findNavController()
pvcm50d1

pvcm50d15#

我用扩展解决了我的问题:

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")
    }
}
uxh89sit

uxh89sit6#

使用简单的<fragment>标记,而不是<androidx.fragment.app.FragmentContainerView>

5ktev3wc

5ktev3wc7#

@friederbluemle的答案还有一个更简单的方法,Assert检查就足够了。

NavHostFragment navHostFragment 
    = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
assert navHostFragment != null : "navHostFragment not found";
NavController navController = navHostFragment.getNavController();
noj0wjuj

noj0wjuj8#

答案很简单-

val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragmentContainerView)

作为导航主机片段

val navController = navHostFragment.navControllermenus.setupWithNavController(navController)
qfe3c7zg

qfe3c7zg9#

我已经将<androidx.fragment.app.FragmentContainerView>更改为<fragment>,它对我很有效。

相关问题