You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Navigation Graph的Kotlin项目:实现CalendarioFragment到PdfFragment的按钮跳转

解决CalendarioFragment跳转至PdfFragment的问题

嘿,我来帮你搞定这个Fragment跳转的事儿!既然你已经用了Navigation Graph,那完全可以在CalendarioFragment本地实现跳转,而且这也是Navigation组件推荐的方式,比直接操作FragmentManager更简洁安全。下面一步步来修正你的代码:

第一步:修正Nav Graph配置里的冗余项

首先看你的Nav Graph代码,calendarioFragment和pdfFragment里的app:defaultNavHost="true"和app:navGraph="@navigation/mobile_navigation"是多余的——这些属性是给NavHostFragment用的,普通的业务Fragment不需要加。修正后的Nav Graph应该是这样:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/calendarioFragment"> <!-- 可根据你的需求调整起始页 -->

    <fragment
        android:id="@+id/calendarioFragment"
        android:name="com.example.aprimorandoconhecimentoss.ui.calendario.CalendarioFragment"
        android:label="fragment_calendario"
        tools:layout="@layout/fragment_calendario">
        <action
            android:id="@+id/action_calendarioFragment_to_pdfFragment"
            app:destination="@id/pdfFragment"
            app:launchSingleTop="false" />
    </fragment>

    <fragment
        android:id="@+id/pdfFragment"
        android:name="com.example.aprimorandoconhecimentoss.ui.pdf.PdfFragment"
        android:label="fragment_pdf"
        tools:layout="@layout/fragment_pdf"/>
</navigation>

第二步:修正CalendarioFragment的跳转逻辑

你的Fragment代码里有两个小问题:一是没有正确使用View Binding,二是获取NavController的方式不对。下面是修正后的完整代码:

class CalendarioFragment : Fragment() {
    private var _binding: FragmentCalendarioBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        // 正确初始化View Binding,无需手动inflate布局
        _binding = FragmentCalendarioBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        // 给按钮设置点击事件,通过NavController完成跳转
        binding.botaoView1.setOnClickListener {
            // 调用Navigation Graph中定义好的跳转动作
            findNavController().navigate(R.id.action_calendarioFragment_to_pdfFragment)
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

关键说明:

  • 不要自己声明var navc = NavController,Fragment里可以直接用findNavController()方法(或view.findNavController())获取关联的NavController,这是Navigation组件的标准用法。
  • 用View Binding获取按钮botaoView1,比findViewById更安全高效,你之前手动inflate布局的方式浪费了Binding的优势。

第三步:检查MainActivity里的NavHost配置

你的MainActivity代码里同时找了R.id.calendarioFragment和R.id.nav_host_fragment_content_main两个NavHost,这会导致冲突。请确保你的Activity布局里只有一个NavHostFragment,并且它的id是nav_host_fragment_content_main,同时这个NavHostFragment的app:navGraph指向你的nav_graph.xml。

修正后的MainActivity核心代码可以简化成这样:

class MainActivity : AppCompatActivity() {
    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        setSupportActionBar(binding.appBarMain.toolbar)

        val drawerLayout: DrawerLayout = binding.drawerLayout
        val navView: NavigationView = binding.navView
        // 只获取布局里NavHostFragment对应的NavController
        val navController = findNavController(R.id.nav_host_fragment_content_main)
        
        appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow,
                R.id.nav_calendario_academico
            ), drawerLayout
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
        navView.setupWithNavController(navController)
    }

    override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.nav_host_fragment_content_main)
        return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
    }
}

为什么之前用supportFragmentManager会崩溃?

直接在Fragment里操作supportFragmentManager容易出问题,比如在Fragment还没完全依附到Activity的时候调用,或者跳转逻辑不符合Navigation的架构规范,导致Fragment栈混乱。而用NavController跳转是Navigation组件封装好的方式,会自动处理Fragment栈的管理,避免这类崩溃。

按照上面的步骤修改后,点击CalendarioFragment里的botaoView1按钮就能正常跳转到PdfFragment啦!

内容的提问来源于stack exchange,提问作者Fabricio Franco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 20:02:48