14

我已经开始使用新的导航组件,我真的很喜欢它!我确实有一个问题 - 当我在图表的起始目的地时,我应该如何处理后退按钮?

这是我现在使用的代码:

findNavController(this, R.id.my_nav_host_fragment)
                .navigateUp()

当我在图表上的任何位置时,它都工作得很好,它把我送回去,但是当我在它的开始时——应用程序崩溃了,因为后台堆栈是空的。

这一切对我来说都很有意义,我只是不知道如何处理它。

虽然我可以检查当前片段的 ID 是否与我知道是图根的 ID 相同,但我正在寻找一种更优雅的解决方案,例如图表中当前位置的布尔标志是否是起始位置与否。

想法?

4

8 回答 8

12

我有一个类似的场景,我想在开始目的地完成活动,并在导航图更下方时执行常规“navigateUp”。我通过一个简单的扩展函数解决了这个问题:

fun NavController.navigateUpOrFinish(activity: AppCompatActivity): Boolean {
return if (navigateUp()) {
    true
} else {
    activity.finish()
    true
}

}

然后这样称呼它:

override fun onSupportNavigateUp() = 
        findNavController(R.id.nav_fragment).navigateUpOrFinish(this)

但是我无法使用 NavigationUI,因为每当我在起始目的地时,它都会隐藏后退箭头。所以而不是:

NavigationUI.setupActionBarWithNavController(this, controller)

我手动控制了主页图标:

setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_navigation_back)
于 2018-10-17T20:23:41.983 回答
8

覆盖onBackPressed您的活动并检查当前目的地是否是起始目的地。

实际上它看起来像这样:

@Override
public void onBackPressed() {
    if (Navigation.findNavController(this,R.id.nav_host_fragment)
            .getCurrentDestination().getId() == R.id.your_start_destination) {
        // handle back button the way you want here
        return;
    }
    super.onBackPressed();
}
于 2018-07-05T18:54:07.537 回答
7

你不应该覆盖“onBackPressed”,你应该覆盖“onSupportNavigateUp”并放在那里

findNavController(this, R.id.my_nav_host_fragment)
            .navigateUp()

来自官方文档: 您还将覆盖 AppCompatActivity.onSupportNavigateUp() 并调用 NavController.navigateUp

https://developer.android.com/topic/libraries/architecture/navigation/navigation-implementing

于 2018-06-21T04:23:06.300 回答
2

在 Jetpack 导航组件中,如果要在弹出片段时执行某些操作,则需要覆盖以下函数。

  1. 在片段中添加 OnBackPressedCallback 以在按​​下底部系统导航栏中的返回时运行您的特殊操作。

     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
    
         onBackPressedCallback = object : OnBackPressedCallback(true) {
             override fun handleOnBackPressed() {
                 //perform your operation and call navigateUp
                findNavController().navigateUp()
             }
         }
     requireActivity().onBackPressedDispatcher.addCallback(onBackPressedCallback)
     }
    
  2. 在片段中添加 onOptionsItemMenu 以处理应用程序内左上角的后退箭头按钮。

     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
    
         setHasOptionsMenu(true)
     }
    
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
       if (item.itemId == android.R.id.home) {
           //perform your operation and call navigateUp
           findNavController().navigateUp()
           return true
       }
       return super.onOptionsItemSelected(item)
    }
    
  3. 如果在主机片段上按下返回时没有要运行的特殊代码,则在 Activity 中使用 onSupportNavigateUp。

     override fun onSupportNavigateUp(): Boolean {
       if (navController.navigateUp() == false){
         //navigateUp() returns false if there are no more fragments to pop
         onBackPressed()
       }
       return navController.navigateUp()
     }
    

请注意,如果片段包含 onOptionsItemSelected(),则不会调用 onSupportNavigateUp()

于 2020-08-29T10:31:12.390 回答
1

由于我的后退按钮工作正常,并且使用 NavController.navigateUp() 在开始目的地后退按钮上崩溃。我已将此代码更改为类似的内容。其他可能性是只检查 currentDestination == startDestination.id 但我想关闭 Activity 并返回其他 Activity。

override fun onSupportNavigateUp() : Boolean {
        //return findNavController(R.id.wizard_nav_host_fragment).navigateUp()
        onBackPressed()
        return true
    }
于 2018-08-02T11:25:11.233 回答
1
/** in your activity **/
private boolean doubleBackToExitPressedOnce = false;
        @RequiresApi(api = Build.VERSION_CODES.M)
        @Override
        public void onBackPressed() {
            int start = Navigation.findNavController(this, R.id.nav_host_fragment).getCurrentDestination().getId();
            if (start == R.id.nav_home) {
                if (doubleBackToExitPressedOnce) {
                    super.onBackPressed();
                    return;
                }
                this.doubleBackToExitPressedOnce = true;
                Toast.makeText(MainActivity.this, "Press back again to exits", Toast.LENGTH_SHORT).show();

                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        doubleBackToExitPressedOnce = false;
                    }
                }, 2000);
            } else {
                super.onBackPressed();
            }
        }
于 2020-05-07T20:50:24.380 回答
0

如果您的意思是“根”导航图的开始(以防万一您有嵌套的导航图),那么您根本不应该显示向上按钮,至少根据导航原则

于 2018-06-19T21:59:40.447 回答
0

只需在您的后退按钮 Onclick 中调用它

 requireActivity().finish()
于 2020-06-29T18:52:18.177 回答