上篇文章说了 showDialog 方法的使用

但是这个方法有很多东西是固定的

比如背景颜色,转换的时长和样式等等,很多东西你很难去自定义

本篇我使用另一个方法showGeneralDialog来做一些自定义

准备工作

同上一章一样,定义一个通用方法

Widget buildButton(
  String text,
  Function onPressed, {
  Color color = Colors.white,
}) {
  return FlatButton(
    color: color,
    child: Text(text),
    onPressed: onPressed,
  );
}

简单使用

这里有几个参数,虽然方法签名上只有 2 个@required注解的参数

但事实上,在我当前的版本环境下,如下代码中所有的参数都是必填项,不填会报错
我的运行环境是这样的

flutter --version
Flutter 1.3.14 • channel dev • https://github.com/flutter/flutter.git
Framework • revision 8e7e435706 (6 days ago) • 2019-03-21 15:31:46 -0700
Engine • revision d4d4883216
Tools • Dart 2.2.1 (build 2.2.1-dev.2.0 None)

代码在这里

showGeneralDialog(
    context: context,
    barrierLabel: "你好",
    barrierDismissible: true,
    transitionDuration: Duration(milliseconds: 300),
    pageBuilder: (BuildContext context, Animation animation,
        Animation secondaryAnimation) {
      return Center(
        child: Material(
          child: Container(
            color: Colors.black.withOpacity(animation.value),
            child: Text("我是一个可变的"),
          ),
        ),
      );
    },
  );
};

Flutter dialog (2) - showGeneralDialog的使用

这里就是弹出的 dialog 了


这里有一个背景色的选项

showGeneralDialog(
  context: context,
  barrierLabel: "你好",
  barrierDismissible: true,
  transitionDuration: Duration(milliseconds: 1000), //这个是时间
  barrierColor: Colors.black.withOpacity(0.5), // 添加这个属性是颜色
  pageBuilder: (BuildContext context, Animation animation,
      Animation secondaryAnimation) {
    return Center(
      child: Material(
        child: Container(
          color: Colors.black.withOpacity(animation.value),
          child: Text("我是一个可变的"),
        ),
      ),
    );
  },
);

Flutter dialog (2) - showGeneralDialog的使用

分析一下属性的作用

context

这个不方便展开解释,可以自己查找 context 的相关文章

barrierLabel

分析一下这个东西的用处
Flutter dialog (2) - showGeneralDialog的使用
Flutter dialog (2) - showGeneralDialog的使用
这里有一个 override,说明虽然属性是私有的,但是父类中可以获取到这个属性

最终到达父类的 ModalRoute
Flutter dialog (2) - showGeneralDialog的使用

看注释的说法,这个是用于语义化的

barrierDismissible

是否可以点击背景关闭

transitionDuration

这个是从开始到完全显示的时间

barrierColor

背景颜色

pageBuilder

这个参数是一个方法,入参是 context,animation,secondaryAnimation,返回一个 Widget

这个 Widget 就是显示在页面上的 dialog

transitionBuilder

路由显示和隐藏的过程,这里入参是 animation,secondaryAnimation 和 child, 其中 child 是 是 pageBuilder 构建的 widget

从其他位置进入

Flutter dialog (2) - showGeneralDialog的使用

代码

buildButton("从左进入", () => showDialogWithOffset(handle: fromLeft)),
buildButton("从右进入", () => showDialogWithOffset(handle: fromRight)),
buildButton("从上进入", () => showDialogWithOffset(handle: fromTop)),
buildButton("从下进入", () => showDialogWithOffset(handle: fromBottom)),
buildButton("从左上进入", () => showDialogWithOffset(handle: fromTopLeft)),
typedef Offset OffsetHandle(Animation animation);
showDialogWithOffset({OffsetHandle handle = fromLeft}) {
  showGeneralDialog(
    context: context,
    barrierColor: Colors.black.withOpacity(0.5),
    barrierLabel: "",
    barrierDismissible: true,
    transitionDuration: const Duration(milliseconds: 1000),
    pageBuilder: (
      BuildContext context,
      Animation animation,
      Animation secondaryAnimation,
    ) {
      return Center(
        child: Material(
          child: Container(
            child: Text("我是dialog"),
          ),
        ),
      );
    },
    transitionBuilder: (ctx, animation, _, child) {
      return FractionalTranslation(
        translation: handle(animation),
        child: child,
      );
    },
  );
}
Offset fromLeft(Animation animation) {
  return Offset(animation.value - 1, 0);
}

Offset fromRight(Animation animation) {
  return Offset(1 - animation.value, 0);
}

Offset fromTop(Animation animation) {
  return Offset(0, animation.value - 1);
}

Offset fromBottom(Animation animation) {
  return Offset(0, 1 - animation.value);
}

Offset fromTopLeft(Animation anim) {
  return fromLeft(anim) + fromTop(anim);
}

这里使用了一个 Widget 叫 FractionalTranslation

接收一个 Offset 作为参数,来移动 child 的 widget

里面的单位是相对,而不是绝对

也就是 Offset 的 x=0 时在原地,-1 为左偏移一屏,1 位右偏移一屏

缩放效果

Flutter dialog (2) - showGeneralDialog的使用

showGeneralDialog(
  context: context,
  barrierLabel: "",
  barrierColor: Colors.black.withOpacity(0.5),
  transitionDuration: const Duration(milliseconds: 500),
  barrierDismissible: true,
  pageBuilder: (BuildContext context, Animation animation,
      Animation secondaryAnimation) {
    return Center(
      child: Image.asset("assets/demo.png"),
    );
  },
  transitionBuilder: (_, anim, __, child) {
    return ScaleTransition(
      scale: anim,
      child: child,
    );
  },
);

利用了 Scaletransition 类,里面需要一个Animation<double> 我这里直接把入参的 anim 传过去就可以了

还支持 alignment 参数,也就是从哪里缩放过来

简单修改一下能达到如下效果

showGeneralDialog(
  context: context,
  barrierLabel: "",
  barrierColor: Colors.black.withOpacity(0.5),
  transitionDuration: const Duration(milliseconds: 500),
  barrierDismissible: true,
  pageBuilder: (BuildContext context, Animation animation,
      Animation secondaryAnimation) {
    return Center(
      child: Image.asset("assets/demo.png"),
    );
  },
  transitionBuilder: (_, anim, __, child) {
    return ScaleTransition(
      alignment: Alignment.bottomCenter, // 添加这个
      scale: anim,
      child: child,
    );
  },
);

Flutter dialog (2) - showGeneralDialog的使用

后记

组合利用 showGeneralDialog 的参数可以达成各种酷炫的效果,比如可以结合TransformMatrix4达到各种效果

完整代码查看github

以上

相关文章:

  • 2022-12-23
  • 2021-11-25
  • 2021-06-12
  • 2021-08-08
  • 2021-12-29
  • 2022-12-23
  • 2022-12-23
  • 2022-01-08
猜你喜欢
  • 2021-11-29
  • 2021-12-02
  • 2021-10-09
  • 2022-12-23
  • 2022-02-04
  • 2021-06-24
  • 2022-12-23
相关资源
相似解决方案