Flutter中AnnotatedRegion设置状态栏颜色不生效问题
问题现象
在Android平台运行下述代码,通过直接替换子组件方式切换页面(未使用Navigator做路由跳转)时,系统导航栏颜色可随页面切换正常更新,状态栏颜色始终无变化。
最小可复现代码
class MyPage extends StatelessWidget { @override Widget build(BuildContext context) { int count = 0; Widget child = FooPage(); return StatefulBuilder( builder: (_, update) { return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () => update(() => child = (++count).isEven ? FooPage() : BarPage()), ), body: child, ); }, ); } } class FooPage extends StatelessWidget { @override Widget build(BuildContext context) { return AnnotatedRegion( value: SystemUiOverlayStyle( statusBarColor: Colors.black, systemNavigationBarColor: Colors.black, ), child: Scaffold( appBar: AppBar(title: Text('Foo')), ), ); } } class BarPage extends StatelessWidget { @override Widget build(BuildContext context) { return AnnotatedRegion( value: SystemUiOverlayStyle( statusBarColor: Colors.grey, systemNavigationBarColor: Colors.grey, ), child: Scaffold( appBar: AppBar(title: Text('Bar')), ), ); } }
问题原因
核心是两个Flutter框架特性叠加导致的:
AnnotatedRegion的样式查找逻辑不是全局检索Widget树中最近的配置,而是按屏幕区域匹配:针对状态栏、导航栏各自所在的屏幕区间,查找该区间内绘制在最上层的组件绑定的SystemUiOverlayStyle作为最终生效值。- 代码中存在两层嵌套Scaffold:外层MyPage里StatefulBuilder返回的Scaffold默认开启
primary: true属性,会自动把body内容的布局起始位置下移一个状态栏高度,避免内容被状态栏遮挡。这就导致塞在body里的FooPage、BarPage,包括内层包裹的AnnotatedRegion,渲染覆盖范围根本碰不到顶部状态栏对应的屏幕区域。系统查询状态栏区域样式时,永远拿不到内层页面配置的statusBarColor,只能读取外层Scaffold提供的默认状态栏样式,因此颜色不会随页面切换变化。 - 底部系统导航栏位于屏幕最底端,外层Scaffold没有配置底部导航栏、底部安全区相关组件,内层页面的渲染范围完全覆盖了底部导航栏区域,因此系统可以正常读取到内层配置的
systemNavigationBarColor,导航栏颜色切换表现正常。
对应的修复方式有两种:
- 删掉外层冗余的Scaffold,直接把要切换的Foo/Bar页面作为StatefulBuilder返回的根组件,避免Scaffold嵌套。
- 给外层Scaffold添加
primary: false配置,让body不再自动偏移状态栏高度,内层AnnotatedRegion的覆盖范围就能包含顶部状态栏区域,配置的颜色即可正常生效。
内容的提问来源于stack exchange,提问作者iDecode
相关产品推荐
相关产品推荐

