背景
公司要求必须使用
Edge-to-Edge不允许使用Android中的theme.xml或style.xml资源文件来通过android:navigationBarColor或android:statusBarColor属性进行对自定义系统Bar的背景进行改色,更不用提android.view.Window.setStatusBarColor和android.view.Window.setNavigationBarColor方法了
如何设置背景色?在哪里设置?为什么在这里设置?我们带着这三个问题,来对这篇文章进行阅读。
如何设置背景色?
直接上代码
dart
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
systemNavigationBarContrastEnforced: false,
systemNavigationBarIconBrightness: Brightness.dark, // 图标颜色-> dark深色;light亮色
systemNavigationBarColor: Colors.white, // 设置导航栏(条)背景颜色
statusBarColor: Colors.white, // 设置状态栏背景颜色
),
);
关键点:
-
开启
Edge-to-Edge沉浸模式 -
systemNavigationBarContrastEnforced设置为false,这个参数在部分Android系统中(特别是MIUI)中是控制颜色"反转"或"强制对比"的关键,设置成false能确保你指定的颜色不被系统覆盖
在哪里设置?
- 使用了
MaterialApp组件作为App入口,那么要在builder返回值之前进行设置:
dart
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(ProviderScope(child: const MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterailApp(
builder: (context,child){
// 在此设置
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
systemNavigationBarContrastEnforced: false,
systemNavigationBarIconBrightness: Brightness.dark,
systemNavigationBarColor: Colors.white,
statusBarColor: Colors.white,
),
);
return child!;
});
}
}
- 没有使用
MaterialApp组件作为App入口,那么要在runApp()方法之前执行设置即可:
dart
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 在此设置
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
systemNavigationBarContrastEnforced: false,
systemNavigationBarIconBrightness: Brightness.dark,
systemNavigationBarColor: Colors.white,
statusBarColor: Colors.white,
)
);
runApp(ProviderScope(child: const MyApp()));
}
为什么在这里设置?
重点 :MaterialApp组件中,无论你设置设置怎样的主题样式,都在组件内部调用一次SystemChrome.setSystemUIOverlayStyle函数,这会让你在MaterialApp组件绘制之前设置的SystemBar背景颜色均被MaterialApp的这一次函数调用覆盖。我们来看下源码
dart
class MaterialApp extends StatefulWidget {
...
@override
State<MaterialApp> createState() => _MaterialAppState();
...
}
class _MaterialAppState extends State<MaterialApp> {
@override
Widget build(BuildContext context) {
Widget result = _buildWidgetApp(context);
...
return ScrollConfiguration(
behavior: widget.scrollBehavior ?? const MaterialScrollBehavior(),
child: HeroControllerScope(controller: _heroController, child: result),
);
}
Widget _buildWidgetApp(BuildContext context) {
final Color materialColor = widget.color ?? widget.theme?.primaryColor ?? Colors.blue;
if (_usesRouter) {
return WidgetsApp.router(
...,
builder: _materialBuilder, // 重点位置
...,
);
}
return WidgetsApp(
...,
builder: _materialBuilder, // 重点位置
...,
);
}
Widget _materialBuilder(BuildContext context, Widget? child) {
final ThemeData theme = _themeBuilder(context); // 重点位置
final Color effectiveSelectionColor =
theme.textSelectionTheme.selectionColor ?? theme.colorScheme.primary.withOpacity(0.40);
final Color effectiveCursorColor =
theme.textSelectionTheme.cursorColor ?? theme.colorScheme.primary;
Widget childWidget = child ?? const SizedBox.shrink();
// 重点位置
if (widget.builder != null) {
childWidget = Builder(
builder: (BuildContext context) {
return widget.builder!(context, child);
},
);
}
...
}
ThemeData _themeBuilder(BuildContext context) {
ThemeData? theme;
...
if (useDarkTheme && highContrast && widget.highContrastDarkTheme != null) {
theme = widget.highContrastDarkTheme;
} else if (useDarkTheme && widget.darkTheme != null) {
theme = widget.darkTheme;
} else if (highContrast && widget.highContrastTheme != null) {
theme = widget.highContrastTheme;
}
theme ??= widget.theme ?? ThemeData();
// 此处的brightness 是 colorScheme.brightness 无论你设置与否都会将SystemBar 设置成light or dark
SystemChrome.setSystemUIOverlayStyle(
theme.brightness == Brightness.dark ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark,
); // 重点位置
return theme;
}
}