onSupportNavigateUp仅在导航起始Fragment被调用问题排查
问题场景
我有一个关联导航图(Navigation Graph)的Activity,工具栏左侧设置返回按钮、右侧设置关闭按钮,相关实现代码如下:
Activity布局代码
<com.google.android.material.appbar.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/appBarColor" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?actionBarSize" android:theme="@style/ThemeOverlay.AppCompat.ActionBar" app:navigationIcon="?homeAsUpIndicator" app:navigationIconTint="?attr/primaryTextColor" app:titleTextColor="?attr/primaryTextColor" tools:layout_height="50dp" /> </com.google.android.material.appbar.AppBarLayout>
Activity onCreate方法初始化逻辑
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment navController = navHostFragment.navController navController.graph = navController.navInflater.inflate(R.navigation.activation_nav_graph) val appBarConfiguration = AppBarConfiguration.Builder().setFallbackOnNavigateUpListener { onSupportNavigateUp() }.build() binding.toolbar.setupWithNavController(navController, appBarConfiguration) NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration)
onCreateOptionsMenu加载关闭按钮菜单
override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.menu_buy_now, menu) return true }
onOptionsItemSelected处理关闭按钮点击事件
override fun onOptionsItemSelected(item: MenuItem): Boolean { if (item.itemId == R.id.action_close) { setResult(Activity.RESULT_CANCELED) finish() return true } return super.onOptionsItemSelected(item) }
自定义onSupportNavigateUp处理向上导航逻辑
override fun onSupportNavigateUp(): Boolean { return when (currentDestination) { R.id.fragment1 -> { setResult(Activity.RESULT_CANCELED) finish() return true } R.id.fragment3 -> { setResult(Activity.RESULT_OK) finish() return true } else -> navController.navigateUp() } }
异常现象
导航图共包含4个Fragment,仅在起始目的地fragment1点击工具栏返回按钮时,自定义的onSupportNavigateUp方法会正常触发并执行对应逻辑;当导航到fragment2、fragment3、fragment4后点击工具栏返回按钮,onSupportNavigateUp方法不会被调用。
问题产生原因
核心原因是Toolbar.setupWithNavController()对导航图标点击事件的默认处理逻辑和预期不符:
- 调用该方法绑定导航控制器后,Navigation组件会自动给Toolbar左侧的返回图标设置专属点击监听,点击时的执行顺序为:
- 首先调用
navController.navigateUp()尝试弹出导航栈的栈顶Fragment:只要当前不在导航图的起始目的地(也就是导航到fragment2、fragment3、fragment4的场景),导航栈内部存在可回退的Fragment条目,navigateUp()会直接执行弹栈操作并返回true,整个点击流程就结束了,根本不会触发你在AppBarConfiguration中设置的FallbackOnNavigateUpListener,自然也就不会调用自定义的onSupportNavigateUp方法。 - 只有当当前处于导航图的起始目的地(也就是fragment1场景),此时导航栈已经没有内部可回退的Fragment,
navigateUp()会返回false,才会触发设置的兜底回调,也就是调用onSupportNavigateUp()执行关闭Activity的逻辑,这就是只有fragment1场景下自定义逻辑生效的原因。
- 首先调用
- 额外注意:代码中调用的
NavigationUI.setupActionBarWithNavController()是给Activity原生ActionBar绑定导航逻辑用的,当前使用的是独立引入的MaterialToolbar,并非Activity默认ActionBar,这行代码实际不生效,还容易引发逻辑混淆,可以直接删掉。
内容的提问来源于stack exchange,提问作者Mehdi Satei
相关产品推荐
相关产品推荐

