在flutter中如何动态更改状态栏的颜色和风格。
前置知识点学习
AnnotatedRegion
`AnnotatedRegion` 是 Flutter 中的一个小部件,用于在特定区域中提供元数据(metadata)以影响某些系统级的行为或外观。它通常用于改变系统 UI 的外观,比如状态栏或导航栏的颜色和风格。
主要用途
1.系统 UI 风格:最常见的用途是与 `SystemUiOverlayStyle` 一起使用,来指定状态栏和导航栏的颜色和图标样式。
2.区域性元数据:它允许在特定的 `Widget` 子树中提供数据,这些数据可以被 Flutter 的其他系统或组件读取和使用。
典型用法
在 Flutter 中,`AnnotatedRegion` 经常用于设置状态栏的样式。通过包裹一个子组件树,并提供一个 `SystemUiOverlayStyle` 值,系统会在该区域应用指定的状态栏样式。
Dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class MyStatusBarDemoPage extends StatelessWidget {
const MyStatusBarDemoPage({super.key});
@override
Widget build(BuildContext context) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: Scaffold(
appBar: AppBar(
title: const Text('AnnotatedRegion Example'),
),
body: const Center(
child: Text('Hello, World!'),
),
));
}
}
注意事项
1.优先级:如果有多个嵌套的 `AnnotatedRegion`,最内层的 `AnnotatedRegion` 的值将会覆盖外层的值。
2.适用范围:`AnnotatedRegion` 适用于需要传递元数据以影响子树行为的场景,主要是系统 UI 样式设置。
3.应用场景:非常适合需要在应用程序的不同页面或部分动态设置状态栏或导航栏风格的情况。
总结
`AnnotatedRegion` 是一个强大的工具,可以在 Flutter 应用的特定区域中设置系统级别的 UI 样式。这使得开发者可以更细粒度地控制应用的视觉风格,特别是在需要根据不同界面动态调整状态栏和导航栏的外观时。通过理解和使用 `AnnotatedRegion`,可以大大增强应用的用户界面体验。
SystemUiOverlayStyle
`SystemUiOverlayStyle` 是 Flutter 中用于定义系统 UI 覆盖层外观的一个类。它主要用于控制状态栏和导航栏的颜色和图标样式。这在提供一致的用户体验和匹配应用的主题时非常有用。
主要属性
`SystemUiOverlayStyle` 提供了一些属性来控制状态栏和导航栏的外观:
1.`statusBarColor`:
- 定义状态栏的背景颜色。
- 仅在 Android 上有效,因为 iOS 的状态栏颜色是由系统控制的。
2.`statusBarIconBrightness`:
- 控制状态栏中图标的亮度(深色或浅色)。
- 可选值为 `Brightness.light` 和 `Brightness.dark`。
- 影响状态栏图标和文字的颜色。
3.`statusBarBrightness`:
- 控制 iOS 状态栏的亮度。
- 用于在 iOS 上设置状态栏内容的颜色(文字和图标)。
4.`systemNavigationBarColor`:
- 定义系统导航栏的背景颜色。
- 仅在 Android 上有效。
5.`systemNavigationBarIconBrightness`:
- 控制导航栏中图标的亮度。
- 适用于 Android。
6.`systemNavigationBarDividerColor`:
- 定义导航栏分隔线的颜色。
- 适用于 Android。
使用示例
可以通过 `SystemChrome.setSystemUIOverlayStyle` 方法应用 `SystemUiOverlayStyle`,或者通过 `AnnotatedRegion` 小部件在特定区域应用。
Dart
class MyStatusBarDemoPage extends StatelessWidget {
const MyStatusBarDemoPage({super.key});
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
statusBarColor: Colors.blue,
statusBarIconBrightness: Brightness.light,
systemNavigationBarColor: Colors.blue,
systemNavigationBarIconBrightness: Brightness.light));
return Scaffold(
appBar: AppBar(
title: const Text('AnnotatedRegion Example'),
),
body: const Center(
child: Text('Hello, World!'),
),
);
}
}
注意事项
1.平台差异:一些属性仅在 Android 上有效(如 `statusBarColor` 和 `systemNavigationBarColor`),而 iOS 上状态栏的外观由系统控制。
2.视觉一致性:确保选择的颜色和亮度组合在各种背景和主题下提供良好的对比度,以保证可读性和用户体验。
3.动态更新:可以在应用的生命周期中多次调用 `SystemChrome.setSystemUIOverlayStyle` 以响应特定页面或组件的需求。
kToolbarHeight
`kToolbarHeight` 是 Flutter 框架中定义的一个常量,代表了标准应用栏(AppBar)的默认高度。它是一个 `double` 类型的值,通常被用来确保应用的布局与 Flutter 的设计规范保持一致。
详细解析
数值:
- `kToolbarHeight` 的值是 `56.0`。这个值是在 Material Design 指南中规定的标准高度,用于 Android 和 iOS 的应用栏。
用途:
- AppBar 高度:在定义 `AppBar` 时,`kToolbarHeight` 确保了应用栏的高度与 Material Design 的标准保持一致。
- 布局计算:在布局计算中,特别是在需要考虑上方留白或空间的情况下,`kToolbarHeight` 可以用于计算其它组件的高度或位置。
- 自定义组件:在实现自定义的 `AppBar` 或类似组件时,可以使用 `kToolbarHeight` 作为高度参考,以保持一致的视觉设计。
使用场景
1.标准 AppBar:
在使用现成的 `AppBar` 组件时,`kToolbarHeight` 是默认的高度,不需要显式指定。但在自定义布局中,你可以使用它来确保一致性。
Dart
AppBar(
title: Text('Example AppBar'),
)
2.自定义 AppBar:
如果你实现自己的 `AppBar`,可以通过实现 `PreferredSizeWidget` 接口来使用 `kToolbarHeight`。
Dart
import 'package:flutter/material.dart';
class MyCustomAppBar extends StatelessWidget implements PreferredSizeWidget {
const MyCustomAppBar({super.key});
@override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
height: kToolbarHeight, // 使用 kToolbarHeight 保持标准高度
child: const Text(
'Custom AppBar',
style: TextStyle(color: Colors.white, fontSize: 20),
),
);
}
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}
3.布局计算:
例如,在布局中计算可用空间时,减去 `kToolbarHeight` 可以确保下方组件不会被 `AppBar` 遮挡。
Dart
double availableHeight = MediaQuery.of(context).size.height - kToolbarHeight;
注意事项
- 一致性:使用 `kToolbarHeight` 可以确保整个应用在使用 `AppBar` 相关布局时保持一致的设计规范。
- 灵活性:虽然 `kToolbarHeight` 提供了一个标准的高度,但在某些情况下,你可能需要根据设计需求调整高度。如果调整,请确保设计的视觉效果和可用性。
总结
`kToolbarHeight` 是一个简单但有用的常量,帮助开发者在 Flutter 应用中保持布局的一致性,特别是在应用栏的设计中。通过使用 `kToolbarHeight`,你可以确保应用在视觉上符合 Material Design 的规范,同时也为用户提供一致的体验。
Size get preferredSize
- 这是一个 getter 方法,返回一个 `Size` 对象。
- `preferredSize` 是 `PreferredSizeWidget` 接口要求的一个属性。它指定了部件的首选大小,在这种情况下,通常用于自定义 `AppBar` 或需要特定大小的任何部件。
`const Size.fromHeight(kToolbarHeight)
- `Size` 是一个类,表示部件的宽度和高度。
- `Size.fromHeight(double height)` 是一个命名构造函数,用于创建一个具有指定高度的 `Size` 对象。宽度被设为无限(`double.infinity`),这意味着宽度是灵活的,可以由父部件或布局系统来确定。
- `kToolbarHeight` 是 Flutter 框架中定义的一个常量,指定了 AppBar 的标准高度,即 `56.0` 逻辑像素。
- `const` 用于创建一个编译时常量,这可以提高性能,因为对象只实例化一次并被重用。
上下文和用法
- 自定义 AppBar 或部件:在创建需要像 `AppBar` 一样行为的自定义部件时,实现 `PreferredSizeWidget` 允许你指定部件的首选大小。这对于布局系统分配正确的空间给该部件非常重要。
- 标准化:通过使用 `kToolbarHeight`,部件遵循了 Material Design 指南中定义的标准 AppBar 高度。这确保了应用程序不同部分的一致性,并符合用户的预期。
IconButton
`IconButton` 是 Flutter 中的一个小部件,用于创建一个具有图标的按钮。它是一个无状态的按钮,用户可以点击它来触发某种动作。`IconButton` 是构建用户界面时常用的组件之一,特别是在需要使用图标而非文本作为交互元素的情况下。
主要属性
1.`icon`:
- 这是一个 `Widget` 类型,通常是一个 `Icon`,表示按钮中显示的图标。
- 例如:`icon: Icon(Icons.add)`
2.`onPressed`:
- 这是一个回调函数,当用户点击按钮时被调用。
- 如果为 `null`,按钮将被禁用并且不会响应点击事件。
- 例如:`onPressed: () { print("Button pressed"); }`
3.`tooltip`:
- 用于提供按钮的描述性文本,当用户长按按钮时显示。通常用于无障碍支持,帮助用户理解按钮的功能。
- 例如:`tooltip: 'Add Item'`
4.`iconSize`:
- 用于设置图标的大小,以逻辑像素为单位。
- 例如:`iconSize: 30.0`
5.`color`:
- 设置图标的颜色。
- 例如:`color: Colors.blue`
6.`padding`:
- 设置按钮的内边距,即图标与按钮边界之间的距离。
- 例如:`padding: EdgeInsets.all(8.0)`
7.`alignment`:
- 控制图标在按钮内的对齐方式。
- 例如:`alignment: Alignment.center`
示例代码
以下是一个简单的 `IconButton` 用法示例:
Dart
IconButton(
icon: Icon(Icons.volume_up),
iconSize: 30.0,
color: Colors.blue,
tooltip: 'Increase volume',
onPressed: () {
print('Volume button clicked');
},
)
使用场景
- 导航栏中的操作按钮,比如返回、菜单、搜索等。
- 表单中的提交或取消操作。
- 增加或减少某些数值,如音量或亮度。
- 任何需要图标作为触发器的交互场景。
总结
`IconButton` 是一个非常灵活的组件,用于在应用程序中以图标形式展示交互按钮。通过其属性,你可以定制图标的大小、颜色、对齐方式以及点击行为等。它广泛用于各种 UI 场景中,为用户提供直观的点击操作。
SafeArea
`SafeArea` 是 Flutter 中的一个布局小部件,用于在应用程序中创建一个"安全"的显示区域。它通过插入合适的填充(padding)来避免应用界面被设备的系统 UI 元素(如状态栏、导航栏、屏幕边角等)遮挡。`SafeArea` 是特别有用的,因为它能够自适应不同设备和屏幕的特殊区域,确保内容的可见性和可用性。
主要功能
- 自动填充:`SafeArea` 会自动检测设备的特殊区域,并为其子组件添加合适的填充,以确保内容不被这些区域遮挡。
- 适应性强:能够适应不同设备和屏幕方向(横屏或竖屏)上的各种系统 UI 元素。
主要属性
1.`child`:
- `SafeArea` 的子组件,即需要保护的内容。
2.`left`, `top`, `right`, `bottom`:
- 布尔值,用于指定是否在对应方向上应用安全填充。
- 例如:`left: false` 表示不在左侧应用填充。
3.`minimum`:
- 用于指定最小填充值。即使计算得出的系统填充值小于这个值,`SafeArea` 也会应用这个最小值。
4.`maintainBottomViewPadding`:
- 当为 `true` 时,即使在键盘弹出时也保持底部填充。这在需要保持底部内容始终可见的情况下非常有用。
使用场景
- 页面布局:在设计页面布局时,确保内容不会被系统 UI 遮挡。
- 全屏应用:在需要全屏显示但又不想被设备特有的区域(如刘海屏、圆角)影响时,使用 `SafeArea` 非常有效。
- 跨平台开发:在开发需要适应不同屏幕尺寸和设备特性的跨平台应用时,`SafeArea` 是一个必备的工具。
总结
`SafeArea` 是 Flutter 中一个非常实用的小部件,用于确保应用程序的内容在各种设备上始终可见且不被遮挡。通过自动适应设备的系统 UI 组件,它为开发者提供了一种简单而有效的方法来处理不同设备上的屏幕布局问题。
代码实现学习
Dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
///鐘舵€佹爮棰滆壊
class MyStatusBarDemoPage extends StatefulWidget {
const MyStatusBarDemoPage({super.key});
@override
_MyStatusBarDemoPageState createState() => _MyStatusBarDemoPageState();
}
class _MyStatusBarDemoPageState extends State<MyStatusBarDemoPage> {
bool customSystemUIOverlayStyle = false;
@override
Widget build(BuildContext context) {
var body = getBody();
if (customSystemUIOverlayStyle) {
return body;
}
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.dark,
child: body,
);
}
getBody() {
return Scaffold(
appBar: const ImageAppBar(),
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
TextButton(
onPressed: () {
setState(() {
customSystemUIOverlayStyle = true;
});
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle.light);
},
style: ButtonStyle(
backgroundColor: ButtonStyleButton.allOrNull<Color>(
Colors.yellowAccent,
),
),
child: const Text("Light"),
),
const SizedBox(
width: 10,
),
TextButton(
onPressed: () {
setState(() {
customSystemUIOverlayStyle = true;
});
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle.dark);
},
style: ButtonStyle(
backgroundColor: ButtonStyleButton.allOrNull<Color>(
Colors.greenAccent,
),
),
child: const Text("Dart"),
),
],
),
),
);
}
}
class ImageAppBar extends StatelessWidget implements PreferredSizeWidget {
const ImageAppBar({super.key});
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Image.asset(
"static/demo.png",
fit: BoxFit.cover,
width: MediaQuery.sizeOf(context).width,
height: kToolbarHeight * 3,
),
SafeArea(
child: IconButton(
color: Colors.white,
icon: const Icon(Icons.arrow_back_ios),
onPressed: () {
Navigator.of(context).pop();
}),
)
],
);
}
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight * 3);
}