用惯了iOS的SVProgressHUD,但是在flutter pub上的并没有找到类似的实现,于是自己实现一个

主要实现四个基本功能

  • Loading显示
  • 成功显示
  • 错误显示
  • 进度显示:环形进度条和文字

库地址

pub.dartlang.org/packages/bm…

  1. dependencies:
  2. bmprogresshud: ^0.0.2
  3. 复制代码

实现效果

  1. 由于HUD是盖在视图上面的,通常是整个页面,故考虑直接在目标Widget上套一层ProgressHUD
  2. 我们需要在特定的地方获取ProgressHUD进行操作,这个有点类似Navigator,参考Navigator的用法,通过of方法获得

实际效果如下

  1. Widget build(BuildContext context) {
  2. return Scaffold(
  3. appBar: AppBar(
  4. title: Text("hud demo"),
  5. ),
  6. body: ProgressHud(
  7. child: Container(
  8. child: Builder(builder: (context) {
  9. return RaisedButton(
  10. onPressed: () async {
  11. ProgressHud.of(context).show(ProgressHudType.loading, "加载中...");
  12. await Future.delayed(const Duration(seconds: 1));
  13. ProgressHud.of(context).dismiss();
  14. },
  15. child: Text("加载数据"),
  16. );
  17. }),
  18. ),
  19. )
  20. );
  21. }
  22. 复制代码

实现效果

1. 显示和隐藏渐变

通过属性opacityAnimationController控制透明度,当透明度为0时候,通过Offstage控制控件的隐藏

  1. class ProgressHudState extends State<ProgressHud> with SingleTickerProviderStateMixin {
  2. AnimationController _animation;
  3. var _opacity = 0.0;
  4. var _isVisible = false;
  5. @override
  6. void initState() {
  7. _animation = AnimationController(
  8. duration: const Duration(milliseconds: 200),
  9. vsync: this
  10. )..addListener(() {
  11. setState(() {
  12. // 修改透明度
  13. _opacity = _animation.value;
  14. });
  15. })..addStatusListener((status) {
  16. if (status == AnimationStatus.dismissed) {
  17. setState(() {
  18. // 隐藏动画结束,隐藏控件
  19. _isVisible = false;
  20. });
  21. }
  22. });
  23. super.initState();
  24. }
  25. ...
  26. }
  27. 复制代码

我们通过动画的执行方向控制动画

  1. // 显示动画
  2. _animation.forward();
  3. setState(() {
  4. _isVisible = true;
  5. });
  6. // 隐藏动画
  7. _animation.reverse();
  8. 复制代码

2. 通过BuildContext获得Element树的ProgressHUD

  1. class ProgressHud extends StatefulWidget {
  2. static ProgressHudState of(BuildContext context) {
  3. return context.ancestorStateOfType(const TypeMatcher<ProgressHudState>());
  4. }
  5. ...
  6. }
  7. 复制代码

3. 创建HUD

  1. Widget _createHudView(Widget child) {
  2. return Stack(
  3. children: <Widget>[
  4. // 如果不想屏蔽用户操作,ignoring设置为true,这里设置为无法响应
  5. IgnorePointer(
  6. ignoring: false,
  7. child: Container(
  8. color: Colors.transparent,
  9. width: double.infinity,
  10. height: double.infinity,
  11. ),
  12. ),
  13. Center(
  14. child: Container(
  15. // 这里设置一定的偏移,因为iPhoneX有下方安全区域,看起来会偏下
  16. margin: EdgeInsets.fromLTRB(10, 10, 10, 10 - widget.offsetY * 2),
  17. decoration: BoxDecoration(
  18. color: Color.fromARGB(255, 33, 33, 33),
  19. borderRadius: BorderRadius.circular(5)
  20. ),
  21. // 设置最小宽高,如果文字比较多,可以自适应
  22. constraints: BoxConstraints(
  23. minHeight: 130,
  24. minWidth: 130
  25. ),
  26. child: Padding(
  27. padding: EdgeInsets.all(12),
  28. child: Column(
  29. mainAxisSize: MainAxisSize.min,
  30. children: <Widget>[
  31. Container(
  32. padding: EdgeInsets.all(15),
  33. child: child,
  34. ),
  35. Container(
  36. child: Text(
  37. _text,
  38. textAlign: TextAlign.center,
  39. style: TextStyle(color: Colors.white, fontSize: 16)
  40. ),
  41. )
  42. ],
  43. ),
  44. ),
  45. ),
  46. ),
  47. ],
  48. );
  49. }
  50. 复制代码

4. 环形进度

通过Painter画两个圆

  1. import 'dart:math';
  2. import 'package:flutter/material.dart';
  3. class CircleProgressBarPainter extends CustomPainter {
  4. final double progress;
  5. final double strokeWidth;
  6. final Color color;
  7. final Color fillColor;
  8. const CircleProgressBarPainter({
  9. this.progress = 0,
  10. this.strokeWidth = 3,
  11. this.color = Colors.grey,
  12. this.fillColor = Colors.white
  13. });
  14. @override
  15. void paint(Canvas canvas, Size size) {
  16. final paint = new Paint()
  17. ..color = this.color
  18. ..style = PaintingStyle.stroke
  19. ..strokeWidth = strokeWidth;
  20. final double diam = min(size.width, size.height);
  21. final centerX = size.width * 0.5;
  22. final centerY = size.height * 0.5;
  23. final radius = diam / 2.0;
  24. canvas.drawCircle(Offset(centerX, centerY), radius, paint);
  25. paint.color = this.fillColor;
  26. // draw in center
  27. var rect = Rect.fromLTWH((size.width - diam) * 0.5, 0, diam, diam);
  28. canvas.drawArc(rect, -0.5 * pi, progress * 2 * pi, false, paint);
  29. }
  30. @override
  31. bool shouldRepaint(CustomPainter oldDelegate) => false;
  32. }
  33. 复制代码

完整代码见这里

Flutter自己实现一个ProgressHUD的更多相关文章

  1. [Flutter] 写第一个 Flutter app,part1 要点

    模拟器中调试元素的布局: Android Studio 右侧边栏 Flutter Inspector,选择 Toggle Debug Paint 打开. 格式化代码: 编辑器中右键 Reformat ...

  2. 【Flutter】Demo1一个名字生成器

    根据官网的例子敲的~效果还是很棒的! 首先导入一个第三方包,可以用来随机生成单词组合 在 pubsepec.yaml下添加如下语句 dependencies: flutter: sdk: flutte ...

  3. 第二篇-用Flutter手撸一个抖音国内版,看看有多炫

    前言 继上一篇使用Flutter开发的抖音国际版 后再次撸一个国内版抖音,大部分功能已完成,主要是Flutter开发APP速度很爽,  先看下图 项目主要结构介绍 这次主要的改动在api.dart 及 ...

  4. 第四篇-用Flutter手撸一个抖音国内版,看看有多炫

    前言 这次对布局进行优化,主要包含了首页tabview pageview 以及添加几个按钮的操作过程.主要使用到stack层叠布局,tabpview和pageview,tabview两个页面,一个关注 ...

  5. 第五篇- 抖音的强大对手来了,用Flutter手撸一个抖音国际版,看看有多炫

    前言 由于中间几个月项目天天加班,导致没没时间更新,最近一段时间对前端进行了重构,加了很多页面,如登录.注册.关注.个人中心等,目前写这个纯属业余个人爱好,所以断断续续的继续在做...... 前端地址 ...

  6. iOS开发之自己封装一个progressHUD控件

    看了几个轻量级的progress view 我觉得KVNProgress做的最漂亮吧 突然我想为什么我自己不封装一个控件 然后我研究了一下KVNProgress KVN简单的界面是由storyboar ...

  7. Flutter新手第一个坑:Could not find com.android.tools.lint:lint-gradle:26.1.1.

    解决方法1:修改build.gradle,注释掉jcenter(),google().使用阿里的镜像.原因是jcenter google库无法访问到导致的问题.虽然我有万能的爬墙工具,开启全局代理依然 ...

  8. 第三篇-用Flutter手撸一个抖音国内版,看看有多炫

    前言 前一篇已经开发了大部分框架,包含视频上下滑动播放,这次将上次未完成的数据显示友好显示,以及底部音乐走马灯特效,另外优化了加载数据的bug,在dart语言里 & 会自动变成&  另 ...

  9. 创建你的第一个Flutter应用程序

    前言 Flutter,Google推出的跨平台开发框架.就在前几天,Flutter的首个发布预览版(Release Preview 1)正式发布! 即将迎来Flutter 正式版(1.0).本篇将带你 ...

随机推荐

  1. Linux 常用命令(遇见了,就记录了 ,随缘吧)

    1.实时查看最后日志(默认10条) # tail -f xxxxxx.log 2.查看结尾多少条日志 # tail -n30 -f xxxx.log 3.根据关键字查询日志 # cat xxxxx.l ...

  2. 微信小程序将外部数据从父组件中传入到子组件

    小程序组件开发遇到一个组件内嵌两个组件,而这两个子组件所使用的数据来自于同一个API,如下图所示. 如果这时候两个子组件各自导入同一个接口就会显得多余.另外的办法是由父组件导入接口数据,再从父组件将接 ...

  3. SpringCloud(一)之我学 Eureka

    1.常用注册中心 1).zookeeper:高一致性(多个节点的数据保持一致): 2).eureka:高可用(系统不能访问的时间很少): 3).consul:上诉两个方案的折中. 高可用:消灭单点故障 ...

  4. Vulnhub DC-9靶机渗透

    信息搜集 nmap -sP 192.168.146.0/24 #主机发现 nmap -A 192.168.146.147 #扫描端口等信息 22端口过滤,80端口开放,同样的从80端口入手. 不是现成 ...

  5. 世界疫情app柱形图显示

    访问云服务器的mysql实现数据的获取.最后通过柱形图的形式将数据显示在页面上: 遇到的主要困难时对于云服务器的mysql连接本地的navicat之间事情,最后通过网上的各种解决办法完成了相关的内容. ...

  6. 初始WebApi(1)

    如果你要问我WebApi是干嘛,我只能说它是的给数据.哈哈哈哈哈,这几天也才刚刚了解了解关于WebApi的知识,今天就来谈谈吧. 1.创建WebApi项目 第一步:选择ASP.NET Web应用程序 ...

  7. Linux C++ 网络编程学习系列(7)——mbedtls编译使用

    mbedtls编译使用 环境: Ubuntu18.04 编译器:gcc或clang 编译选项: 静态编译使用 1. mbedtls源码 下载地址: https://github.com/ARMmbed ...

  8. 钩子函数 Function类

    Function 为 com.google.common.base包下接口类: public interface Function<F, T> { @Nullable T apply(@N ...

  9. 数据表记录包含表索引和数值(int范围的整数),请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照key值升序进行输出

    此题如果直接使用有序的TreeMap就不需要这样折腾: 1.map的key值唯一性,故就不在需要set集合来去重 2.使用map后利用key的唯一性,把序列号相同的数据直接加在一起,代码会很简洁 pa ...

  10. d3.js v4曲线图的拖拽功能实现Zoom

    zoom缩放案例 源码:https://github.com/HK-Kevin/d...:demo:https://hk-kevin.github.io/d3...: 原理:通过zoom事件来重新绘制 ...