小菜继续整理 Flutter 中日常用到的小知识点.
1. WillPopScope 返回导航
小菜在做 Android 时经常会双击快速点击返回键弹出退出对话框, 之后在进行操作, 而 Flutter 也提供了监听返回导航的 , 其中的回调方法返回一个 boolean 类型, true 时退出页面, false 时不退出, 小菜设置在 1500ms 之内连续点击两次弹出提示框. 在对时间进行监听时, 小菜用到 Duration 可以设置时分秒毫秒微秒等, 方便快捷.
- class _MyHomePageState extends State<MyHomePage> {
- DateTime _lastPressedAt;
- @override
- Widget build(BuildContext context) {
- return WillPopScope(
- child: Scaffold(
- body: new SafeArea(
- top: true,
- child: new Center(child: childHomeWidget(context)),
- ),
- onWillPop: () async {
- if (_lastPressedAt == null ||
- DateTime.now().difference(_lastPressedAt)>
- Duration(milliseconds: 1500)) {
- _lastPressedAt = DateTime.now();
- return false;
- } else {
- return showDialog(
- context: context,
- barrierDismissible: false,
- builder: (BuildContext context) {
- return ExitDialog(
- context: '您确定要退出吗?',
- onCancelEvent: () {
- Navigator.pop(context, false);
- },
- onSureEvent: () {
- Navigator.pop(context, true);
- });
- });
- }
- });
- }
- }
2. onScaleUpdate 缩放监听
小菜在处理图片时可能需要用到图片缩放方面的监听事件, 查阅资料发现基本的 GestureDetector 便有监听方法 , 这是一个回调方法, 监听缩放时的比例和角度 , 其中 scale 和 rotation 均不可为空.
- class _GesturePageState extends State<GesturePage> {
- var _width = 300.0;
- var _height;
- @override
- Widget build(BuildContext context) {
- return new SafeArea(
- top: false,
- child: Scaffold(
- appBar: new AppBar(
- title: Text('图片缩放'),
- ),
- body: Center(
- child: GestureDetector(
- child: Image.asset('images/icon_hzw02.jpg', width: _width),
- onScaleUpdate: (ScaleUpdateDetails details) {
- setState(() {
- var num = details.scale.clamp(0.5, 2.0);
- _width = 200 * num;
- // _width = 400;
- });
- }))));
- }
- }
3. FadeInImage 淡入图片
小菜在上一篇博客中尝试了一下 CachedNetworkImage 缓存图片, 这次发现了另一种 淡入式图片, 在图片的加载过程中有一个简单的动画效果, 用户体验更好. FadeInImage 可加载本地图片 / 网络图片 / 内存图片, 使用方式很简单. 除了基本的图片大小 / 状态等, placeholder 和 image 两个参数必须存在, 否则报异常.
- FadeInImage(
- placeholder: AssetImage('images/icon_copylink.png'),
- image: AssetImage('images/icon_hzw01.jpg')
- // image: NetworkImage("https://flutter.io/images/catalog-widget-placeholder.png"
- )
对于加载网络图片, FadeInImage 还提供了两种更便利的加载方式:
- FadeInImage.assetNetwork
- FadeInImage.assetNetwork(
- placeholder: 'images/icon_copylink.png',
- placeholderScale: 2.0,
- image: 'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=703702342,1604162245&fm=26&gp=0.jpg')),
- FadeInImage.memoryNetwork
- FadeInImage.memoryNetwork(
- placeholder: kTransparentImage,
- image: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1544938569112&di=feeab11968f3870520482630563c4f54&imgtype=0&src=http://i1.hdslb.com/bfs/archive/ac5c906111130579c6909aae47f6656e20d0906b.jpg')),
Tips:
上述两种方式一般只用来加载网络图;
FadeInImage.memoryNetwork 方式展位图用 Uint8List 资源 (byte 数组) 加载, 通常使用 透明来处理;
FadeInImage.assetNetwork 占位图默认不是居中, 位置需要自己调整.
4. ToolTip 提示框
小菜在使用 FloatingActionButton 时, 长按按钮会出现一个简短的提示信息, 很方便, 故特意学习一下 ToolTip, 以后方便使用.
ToolTip 默认是在点击范围底部展示, 当底部范围不够时在顶部展示, 也可以通过 preferBelow 进行设置, true 为底部, false 为顶部; 而 ToolTip 展示的位置及大小可以通过 verticalOffset 和 height 等属性共同配置.
- Widget toolTipItemWid(var str, var color) {
- return Tooltip(
- message: str,
- child: Container(
- width: 150.0,
- height: 60.0,
- color: color,
- child: Center(
- child: Text(str,
- style: TextStyle(color: Colors.white, fontSize: 16.0)))));
- }
5. AspectRatio 比例布局
小菜在学习大神博客时, 发现 可以设置布局的比例. 设置父布局的宽或高可以根据 aspectRatio 展示子布局大小, 比例 aspectRatio=width/high, 注意 aspectRatio 必须存在且大于 0.
- Widget aspectRatioWid() {
- return Container(
- height: 200.0,
- child: new AspectRatio(
- aspectRatio: 0.5,
- child: new Container(color: Colors.lightBlueAccent)));
- }
如上即会生成一个宽为 400 高为 200 的矩形, 但实际情况还有很多, 小菜逐一尝试, width 和 height 均为根据比例计算之后的子布局大小, ScreenWidth 和 ScreenHeight 分别为屏幕宽高:
5.1 父布局宽固定 && width <= ScreenWidth && height <= ScreenHeight
- return Container(
- width: 200.0,
- child: new AspectRatio(
- aspectRatio: 0.5,
- child: new Container(color: Colors.lightBlueAccent)));
此时在屏幕上正常显示比例样式, 如图:
5.2 父布局宽或高固定 && width <= ScreenWidth && height> ScreenHeight
- return Container(
- width: 300.0,
- child: new AspectRatio(
- aspectRatio: 0.5,
- child: new Container(color: Colors.lightBlueAccent)));
若按比例计算, width=300.0 & height=600.0, 但 height 超过屏幕高度, 所以全部占满, 如图:
5.3 父布局宽固定 && width> ScreenWidth && height <= ScreenHeight
- return Container(
- width: 600.0,
- child: new AspectRatio(
- aspectRatio: 2,
- child: new Container(color: Colors.lightBlueAccent)));
若按比例计算, width=600.0 & height=300.0, 但 width 超过屏幕高度, 所以全部占满, 如图:
5.4 父布局宽固定 && width> ScreenWidth && height> ScreenHeight
- return Container(
- width: 600.0,
- child: new AspectRatio(
- aspectRatio: 0.5,
- child: new Container(color: Colors.lightBlueAccent)));
若按比例计算, width=600.0 & height=1200.0, 但 width 和 height 均超过屏幕高度, 所以全部占满, 如图:
5.5 父布局高固定 && width <= ScreenWidth && height> ScreenHeight
- return Container(
- height: 600.0,
- child: new AspectRatio(
- aspectRatio: 2,
- child: new Container(color: Colors.lightBlueAccent)));
效果如 5.2;
5.6 父布局高固定 && width> ScreenWidth && height <= ScreenHeight
- return Container(
- height: 300.0,
- child: new AspectRatio(
- aspectRatio: 2,
- child: new Container(color: Colors.lightBlueAccent)));
效果如 5.3;
5.7 父布局高固定 && width> ScreenWidth && height> ScreenHeight
- return Container(
- height: 600.0,
- child: new AspectRatio(
- aspectRatio: 2,
- child: new Container(color: Colors.lightBlueAccent)));
效果如 5.4.
如果有不对的地方还希望多多指教!
来源: https://yq.aliyun.com/articles/688115