前置知识点整理
Wrap
在 Flutter 中,`Wrap` 是一种布局小部件,用于在水平或垂直方向上自动换行子小部件。它类似于 CSS 中的 `flex-wrap`,适合用于需要动态换行的布局场景,比如标签云、照片网格等。
`Wrap` 的基本属性
- `direction`:决定子小部件的布局方向,默认为 `Axis.horizontal`。可以设置为 `Axis.vertical`,这将使子小部件从上到下排列。
- `alignment`:沿主轴对齐子小部件的方式。类似于 `Row` 和 `Column` 的 `mainAxisAlignment`。
- `spacing`:在主轴方向上的子小部件之间的间距。
- `runAlignment`:沿交叉轴对齐每个运行中的子小部件。类似于 `Column` 的 `crossAxisAlignment`。
- `runSpacing`:在交叉轴方向上的运行之间的间距。
- `clipBehavior`:决定超出边界的子小部件的裁剪方式。
简单示例
Dart
import 'package:flutter/material.dart';
class WrapPageDemo extends StatelessWidget {
const WrapPageDemo({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Wrap Example')),
body: Center(
child: Wrap(
direction: Axis.horizontal,
alignment: WrapAlignment.start,
spacing: 8.0,
// 主轴(水平)方向上的间距
runAlignment: WrapAlignment.center,
runSpacing: 4.0,
// 交叉轴(垂直)方向上的间距
children: List.generate(10, (index) {
return Chip(
label: Text('Item $index'),
avatar: CircleAvatar(
backgroundColor: Colors.blue,
child: Text('$index'),
),
);
}),
),
),
),
);
}
}
使用场景
- 动态布局:当您不知道子小部件的确切数量或者它们的大小可能会改变时,`Wrap` 可以帮助实现自适应布局。
- 响应式设计:在不同屏幕尺寸下需要不同的布局时,`Wrap` 可以动态地调整行和列的数量。
- 标签或按钮组:用于显示一组标签、按钮或其他小部件,这些小部件需要根据可用空间自动换行。
通过 `Wrap`,开发者可以轻松实现自适应的、灵活的布局,而不必手动管理换行和对齐问题。
EdgeInsets.symmetric
`EdgeInsets.symmetric` 是 Flutter 中的一个用于创建对称填充或边距的构造方法。它属于 `EdgeInsets` 类,这个类用于定义四个方向(上、下、左、右)的填充或边距。
`EdgeInsets.symmetric` 使用
`EdgeInsets.symmetric` 允许您同时指定水平和垂直方向的填充或边距,而不必为每个方向单独设置。它是 `EdgeInsets` 的一个便利构造方法,用于简化代码。
构造函数
Dart
EdgeInsets.symmetric({
double horizontal = 0.0,
double vertical = 0.0,
})
- `horizontal`: 控制左和右两侧的填充或边距。
- `vertical`: 控制上和下两侧的填充或边距。
使用场景
- 对称布局: 当您需要在小部件的两侧设置相同的边距或填充时,使用 `EdgeInsets.symmetric` 可以让代码更简洁。
- 快速布局调整: 通过调整水平和垂直参数,可以快速实现对称的视觉效果,非常适合用于按钮、卡片等需要均匀填充的 UI 组件。
`EdgeInsets.symmetric` 是一个非常有用的工具,用于简化 UI 布局和调整填充与边距,特别是在需要对称的情况下。
BoxDecoration
`BoxDecoration` 是 Flutter 中用于绘制容器(`Container`)背景的一个类。它允许您使用颜色、渐变、图像、边框和阴影等来装饰容器,从而创建丰富的视觉效果。`BoxDecoration` 常用于提升应用界面的美观性和用户体验。
`BoxDecoration` 的主要属性
以下是 `BoxDecoration` 类的主要属性及其用途:
1.`color`:
- 设置容器的背景颜色。
- 例如:`color: Colors.blue`。
2.`gradient`:
- 设置背景的渐变色。
- 支持线性渐变(`LinearGradient`)、径向渐变(`RadialGradient`)等。
- 例如:
Dart
gradient: LinearGradient(
colors: [Colors.red, Colors.blue],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
)
3.`image`:
- 设置背景图像。
- 使用 `DecorationImage` 来指定图像及其适配方式。
- 例如:
Dart
image: DecorationImage(
image: AssetImage('assets/background.png'),
fit: BoxFit.cover,
)
4.`border`:
- 设置容器的边框。
- 可以使用 `Border.all()` 创建统一的边框,或使用 `Border()` 设置不同方向的边框。
- 例如:
Dart
border: Border.all(
color: Colors.black,
width: 2.0,
)
5.`borderRadius`:
- 设置容器的圆角边框。
- 使用 `BorderRadius.circular()` 为四个角设置相同的圆角半径。
- 例如:`borderRadius: BorderRadius.circular(10.0)`
6.`boxShadow`:
- 设置容器的阴影效果。
- 使用 `BoxShadow` 来定义阴影的颜色、模糊半径、偏移等。
- 例如:
Dart
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 7,
offset: Offset(0, 3), // changes position of shadow
),
]
7.`shape`:
- 设置容器的形状。
- 可以是 `BoxShape.rectangle`(默认为矩形)或 `BoxShape.circle`。
- 注意:如果使用 `BoxShape.circle`,`borderRadius` 会被忽略。
示例代码
Dart
import 'package:flutter/material.dart';
class MyBoxDecorationDemoPage extends StatelessWidget {
const MyBoxDecorationDemoPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BoxDecoration Example'),
),
body: Center(
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 2,
offset: const Offset(3, 3))
],
border: Border.all(color: Colors.white, width: 2)),
child: const Center(
child: Text(
'Hello, Flutter!',
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
),
),
);
}
}
应用场景
`BoxDecoration` 非常适合用于需要自定义背景的组件,例如:
- 卡片视图:可以用来创建带有阴影和圆角的卡片。
- 按钮:通过 `BoxDecoration` 和 `GestureDetector`,可以创建自定义的按钮样式。
- 用户头像:结合 `BoxShape.circle` 和 `DecorationImage`,可以用来裁剪圆形头像。
通过 `BoxDecoration`,您可以灵活地控制容器的外观,使得 Flutter 应用能够根据设计需求进行细致的定制。
标签简单实现
Dart
import 'package:flutter/material.dart';
class MyTagDemoPage extends StatelessWidget {
const MyTagDemoPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("TagDemoPage"),
),
body: Wrap(
children: <Widget>[
const MyTagItem("Start"),
for (var item in tags) MyTagItem(item),
const MyTagItem("End"),
],
),
);
}
}
class MyTagItem extends StatelessWidget {
final String text;
const MyTagItem(this.text, {super.key});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
decoration: BoxDecoration(
color: Colors.blueAccent.withAlpha(50),
borderRadius: const BorderRadius.all(Radius.circular(5))),
child: Text(text),
);
}
}
const List<String> tags = [
"AAAAAAAAAAAAA",
"BBBBBBBBBBB",
"C",
"DD",
"EEEEEEEEE",
"1111111111",
"222",
"%%%",
"****",
"@@@",
"**",
"ssssss"
];