Flutter dialog (2) - showGeneralDialog的使用
文章目录
上篇文章 说了 showDialog 方法的使用
但是这个方法有很多东西是固定的
比如背景颜色,转换的时长和样式等等,很多东西你很难去自定义
本篇我使用另一个方法showGeneralDialog
来做一些自定义
准备工作
同上一章一样,定义一个通用方法
1Widget buildButton(
2 String text,
3 Function onPressed, {
4 Color color = Colors.white,
5}) {
6 return FlatButton(
7 color: color,
8 child: Text(text),
9 onPressed: onPressed,
10 );
11}
简单使用
这里有几个参数,虽然方法签名上只有 2 个@required
注解的参数
但事实上,在我当前的版本环境下,如下代码中所有的参数都是必填项,不填会报错 我的运行环境是这样的
1flutter --version
2Flutter 1.3.14 • channel dev • https://github.com/flutter/flutter.git
3Framework • revision 8e7e435706 (6 days ago) • 2019-03-21 15:31:46 -0700
4Engine • revision d4d4883216
5Tools • Dart 2.2.1 (build 2.2.1-dev.2.0 None)
代码在这里
1showGeneralDialog(
2 context: context,
3 barrierLabel: "你好",
4 barrierDismissible: true,
5 transitionDuration: Duration(milliseconds: 300),
6 pageBuilder: (BuildContext context, Animation animation,
7 Animation secondaryAnimation) {
8 return Center(
9 child: Material(
10 child: Container(
11 color: Colors.black.withOpacity(animation.value),
12 child: Text("我是一个可变的"),
13 ),
14 ),
15 );
16 },
17 );
18};
这里就是弹出的 dialog 了
这里有一个背景色的选项
1showGeneralDialog(
2 context: context,
3 barrierLabel: "你好",
4 barrierDismissible: true,
5 transitionDuration: Duration(milliseconds: 1000), //这个是时间
6 barrierColor: Colors.black.withOpacity(0.5), // 添加这个属性是颜色
7 pageBuilder: (BuildContext context, Animation animation,
8 Animation secondaryAnimation) {
9 return Center(
10 child: Material(
11 child: Container(
12 color: Colors.black.withOpacity(animation.value),
13 child: Text("我是一个可变的"),
14 ),
15 ),
16 );
17 },
18);
分析一下属性的作用
context
这个不方便展开解释,可以自己查找 context 的相关文章
barrierLabel
分析一下这个东西的用处
这里有一个 override,说明虽然属性是私有的,但是父类中可以获取到这个属性
最终到达父类的 ModalRoute
看注释的说法,这个是用于语义化的
barrierDismissible
是否可以点击背景关闭
transitionDuration
这个是从开始到完全显示的时间
barrierColor
背景颜色
pageBuilder
这个参数是一个方法,入参是 context,animation,secondaryAnimation,返回一个 Widget
这个 Widget 就是显示在页面上的 dialog
transitionBuilder
路由显示和隐藏的过程,这里入参是 animation,secondaryAnimation 和 child, 其中 child 是 是 pageBuilder 构建的 widget
从其他位置进入
代码
1buildButton("从左进入", () => showDialogWithOffset(handle: fromLeft)),
2buildButton("从右进入", () => showDialogWithOffset(handle: fromRight)),
3buildButton("从上进入", () => showDialogWithOffset(handle: fromTop)),
4buildButton("从下进入", () => showDialogWithOffset(handle: fromBottom)),
5buildButton("从左上进入", () => showDialogWithOffset(handle: fromTopLeft)),
1typedef Offset OffsetHandle(Animation animation);
1showDialogWithOffset({OffsetHandle handle = fromLeft}) {
2 showGeneralDialog(
3 context: context,
4 barrierColor: Colors.black.withOpacity(0.5),
5 barrierLabel: "",
6 barrierDismissible: true,
7 transitionDuration: const Duration(milliseconds: 1000),
8 pageBuilder: (
9 BuildContext context,
10 Animation animation,
11 Animation secondaryAnimation,
12 ) {
13 return Center(
14 child: Material(
15 child: Container(
16 child: Text("我是dialog"),
17 ),
18 ),
19 );
20 },
21 transitionBuilder: (ctx, animation, _, child) {
22 return FractionalTranslation(
23 translation: handle(animation),
24 child: child,
25 );
26 },
27 );
28}
1Offset fromLeft(Animation animation) {
2 return Offset(animation.value - 1, 0);
3}
4
5Offset fromRight(Animation animation) {
6 return Offset(1 - animation.value, 0);
7}
8
9Offset fromTop(Animation animation) {
10 return Offset(0, animation.value - 1);
11}
12
13Offset fromBottom(Animation animation) {
14 return Offset(0, 1 - animation.value);
15}
16
17Offset fromTopLeft(Animation anim) {
18 return fromLeft(anim) + fromTop(anim);
19}
这里使用了一个 Widget 叫 FractionalTranslation
接收一个 Offset 作为参数,来移动 child 的 widget
里面的单位是相对,而不是绝对
也就是 Offset 的 x=0 时在原地,-1 为左偏移一屏,1 位右偏移一屏
缩放效果
1showGeneralDialog(
2 context: context,
3 barrierLabel: "",
4 barrierColor: Colors.black.withOpacity(0.5),
5 transitionDuration: const Duration(milliseconds: 500),
6 barrierDismissible: true,
7 pageBuilder: (BuildContext context, Animation animation,
8 Animation secondaryAnimation) {
9 return Center(
10 child: Image.asset("assets/demo.png"),
11 );
12 },
13 transitionBuilder: (_, anim, __, child) {
14 return ScaleTransition(
15 scale: anim,
16 child: child,
17 );
18 },
19);
利用了 Scaletransition 类,里面需要一个Animation<double>
我这里直接把入参的 anim 传过去就可以了
还支持 alignment 参数,也就是从哪里缩放过来
简单修改一下能达到如下效果
1showGeneralDialog(
2 context: context,
3 barrierLabel: "",
4 barrierColor: Colors.black.withOpacity(0.5),
5 transitionDuration: const Duration(milliseconds: 500),
6 barrierDismissible: true,
7 pageBuilder: (BuildContext context, Animation animation,
8 Animation secondaryAnimation) {
9 return Center(
10 child: Image.asset("assets/demo.png"),
11 );
12 },
13 transitionBuilder: (_, anim, __, child) {
14 return ScaleTransition(
15 alignment: Alignment.bottomCenter, // 添加这个
16 scale: anim,
17 child: child,
18 );
19 },
20);
后记
组合利用 showGeneralDialog 的参数可以达成各种酷炫的效果,比如可以结合Transform
和Matrix4
达到各种效果
完整代码查看 github
以上