如何使用导航组件处理片段内的向上按钮

How to handle up button inside fragment using Navigation Components

我正在制作一个简单的笔记应用程序,我有 2 个带导航组件的片段,一个片段有笔记列表,另一个用于编辑或创建新笔记。

MainActivity中我添加了

val navController = this.findNavController(R.id.host_fragment)
NavigationUI.setupActionBarWithNavController(this, navController)

然后覆盖onSupportNavigateUp()

override fun onSupportNavigateUp(): Boolean {
        val navController = this.findNavController(R.id.host_fragment)
        return navController.navigateUp()
    }

NoteEditFragment

requireActivity().onBackPressedDispatcher.addCallback(this) {
        saveOrUpdateNote(noteId, note)
    }

现在在设备中按下 "back button" 时一切正常,但是当我按下屏幕左上角的 "up button" 时会触发 onBackPressedDispatcher.addCallback()

我的问题是:如何处理 NoteEditFragment 中的这个向上按钮?

提前致谢

终于找到了解决方法。

首先在 activity onCreate 方法中,我必须像以前那样连接导航:

val navController = this.findNavController(R.id.host_fragment)
NavigationUI.setupActionBarWithNavController(this, navController)

然后还在MainActivity覆盖onSupportNavigateUp()

override fun onSupportNavigateUp(): Boolean
{
    val navController = this.findNavController(R.id.host_fragment)
    return navController.navigateUp()
}

然后在 Fragment onCreateView 我必须启用选项菜单:

setHasOptionsMenu(true)

然后在 fragment 我覆盖了 onOptionsItemSelected :

override fun onOptionsItemSelected(item: MenuItem): Boolean
{
    // handle the up button here
    return NavigationUI.onNavDestinationSelected(item!!,
        view!!.findNavController())
            || super.onOptionsItemSelected(item)
}

注意:我认为如果你有多个选项菜单,那么我认为你必须做一个 when (item) 语句来检查选择了哪个选项。

此外,如果您想处理设备后退按钮,那么您可以在 fragment onCreateViewMethod 中这样做:

requireActivity().onBackPressedDispatcher.addCallback(this)
    {
        // handle back button

// change this line to whatever way you chose to navigate back          
findNavController().navigate(NoteEditFragmentDirections.actionNoteEditFragmentToNoteListFragment())
        }

如果你使用 noActionBar 主题并且你想使用你自己的工具栏作为片段的 actionBar,你可以使用这个方法

在主机中activity

override fun onSupportNavigateUp(): Boolean {
    return findNavController(R.id.navHostFragment).navigateUp()
}

在fragment的onCreateView中

(activity as AppCompatActivity).setSupportActionBar(binding.toolbar)
(activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true)

我认为接受的答案有点乱。所以,我找到了一个干净的代码。它非常适合我的用例,因为按下设备后退按钮时我不需要做任何特别的事情。所以这里有相同需求的朋友可以按照我的代码来做。

在 MainActivity 的 onCreate 中:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val navController = findNavController(R.id.nav_host_fragment)
    appBarConfiguration = AppBarConfiguration(navController.graph)
    // Check if androidx.navigation.ui.NavigationUI.setupActionBarWithNavController is imported
    // By default title in actionbar is used from the fragment label in navigation graph
    // To use the app name, remove label else if you want to add customized label specify it there
    setupActionBarWithNavController(this, navController, appBarConfiguration)

    ...

  }

同样,在 MainActivity 本身中:

override fun onSupportNavigateUp(): Boolean {
    val navController = findNavController(R.id.fragment)
    // Check if androidx.Navigation.ui navigateUp is imported and used
    return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}

我添加了评论以便更好地理解。如果您认为答案有帮助,请点赞。谢谢你。快乐发展:)

编辑 1: 无需在片段中使用 supportActionBar.setDisplayHomeAsUpEnabled(true)。 AppBarConfiguration 会处理它。

以非常简单的方式,您只需要在 Activity 上设置 supportNavigateUp。

主要Activity:

private lateinit var navController: NavController

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

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

    setupActionBarWithNavController(navController)
}

override fun onSupportNavigateUp(): Boolean {
    return navController.navigateUp() || super.onSupportNavigateUp()
}

在我的例子中它起作用了