Jetpack Navigation搭配Material Toolbar导航时工具栏渲染闪烁问题咨询
问题原因
- 版本缺陷:你使用的Jetpack Navigation 2.3.5版本存在Toolbar配置与导航转场不同步的已知问题,
setupWithNavController的执行时机晚于转场动画的触发时机,导致视觉上先出现默认配置再更新为自定义配置。 - 共用Toolbar的状态复用问题:如果你的MaterialToolbar放在Activity布局中,由所有Fragment共用,导航时Navigation会优先读取导航图中目的地的
label属性,先给Toolbar设置默认标题、系统返回图标,等当前Fragment的onViewCreated执行自定义配置时才覆盖原有属性,两者的时间差就会产生闪烁。 - 样式未全局适配:Navigation自动设置的标题会沿用Toolbar的默认样式,如果你没有在主题中统一配置Toolbar的标题字号、颜色、导航图标样式,就会出现初始样式不符合预期的问题。
解决方案
方案1:升级Navigation版本(最优先)
直接将Navigation依赖升级到2.4.0及以上版本,官方在该版本中修复了大量Navigation UI与Toolbar的同步缺陷,绝大多数同类闪烁问题会直接修复。
方案2:Fragment独立管理Toolbar
不要共用Activity的Toolbar,将Toolbar放到每个Fragment的私有布局中,每个Fragment仅管理自己布局内的Toolbar:
- 导航时新Fragment的Toolbar会跟随自身视图一起渲染,不会复用前一个页面的Toolbar状态
- 避免了跨页面的Toolbar属性冲突,从根源上消除闪烁。
方案3:提前在Activity中监听导航变更配置Toolbar
如果必须共用Activity的Toolbar,不要在每个Fragment的onViewCreated中配置Toolbar,改为在Activity中注册OnDestinationChangedListener,导航触发时就直接设置对应页面的Toolbar属性:
navController.addOnDestinationChangedListener { _, destination, _ -> when(destination.id) { R.id.screen_c -> { toolbar.title = "SCREEN C" toolbar.setNavigationIcon(R.drawable.custom_back_c) toolbar.inflateMenu(R.menu.menu_c) } R.id.screen_d -> { toolbar.title = "SCREEN D" toolbar.setNavigationIcon(R.drawable.custom_back_d) toolbar.menu.clear() } // 其他页面配置 } }
该方案保证导航触发时Toolbar直接加载正确配置,没有二次修改的时间差。
方案4:禁用自动配置,手动控制Toolbar属性
如果要保留原有调用逻辑,调用setupWithNavController后立即手动覆盖Toolbar属性,避免默认配置残留:
val navController = NavHostFragment.findNavController(fragment) val appBarConfiguration = AppBarConfiguration(navController.graph) setupWithNavController(navController, appBarConfiguration) // 手动覆盖属性 toolbar.apply { title = "当前页面标题" setTitleTextColor(ContextCompat.getColor(context, R.color.title_color)) setTitleTextSize(TypedValue.COMPLEX_UNIT_SP, 16f) setNavigationIcon(R.drawable.custom_back_icon) // 控制菜单显隐 menu.clear() if (需要显示菜单) inflateMenu(R.menu.current_menu) }
同时在主题中统一配置MaterialToolbar的默认样式,避免初始样式异常:
<style name="AppTheme.Toolbar" parent="Widget.MaterialComponents.Toolbar"> <item name="titleTextColor">@color/toolbar_title</item> <item name="titleTextAppearance">@style/ToolbarTitleText</item> <item name="navigationIcon">@drawable/ic_default_back</item> </style>
内容的提问来源于stack exchange,提问作者Sarbyn
相关产品推荐
相关产品推荐

