zoukankan      html  css  js  c++  java
  • Flutter自己实现一个ProgressHUD

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

    主要实现四个基本功能

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

    库地址

    pub.dartlang.org/packages/bm…

    dependencies:
      bmprogresshud: ^0.0.2
    复制代码

    实现效果

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

    实际效果如下

    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text("hud demo"),
        ),
        body: ProgressHud(
          child: Container(
            child: Builder(builder: (context) {
              return RaisedButton(
                onPressed: () async {
                  ProgressHud.of(context).show(ProgressHudType.loading, "加载中...");
                  await Future.delayed(const Duration(seconds: 1));
                  ProgressHud.of(context).dismiss();
                },
                child: Text("加载数据"),
              );
            }),
          ),
        )
      );
    }
    复制代码

    实现效果

    1. 显示和隐藏渐变

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

    class ProgressHudState extends State<ProgressHud> with SingleTickerProviderStateMixin {
      AnimationController _animation;
      var _opacity = 0.0;
      var _isVisible = false;
    
      @override
      void initState() {
        _animation = AnimationController(
          duration: const Duration(milliseconds: 200), 
          vsync: this
        )..addListener(() {
          setState(() {
            // 修改透明度
            _opacity = _animation.value;
          });
        })..addStatusListener((status) {
          if (status == AnimationStatus.dismissed) {
            setState(() {
              // 隐藏动画结束,隐藏控件
              _isVisible = false;          
            });
          }
        });
        super.initState();
      }
    
      ...
    }
    复制代码

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

    // 显示动画
    _animation.forward();
    setState(() {
      _isVisible = true;
    });
    
    // 隐藏动画
    _animation.reverse();
    复制代码

    2. 通过BuildContext获得Element树的ProgressHUD

    class ProgressHud extends StatefulWidget {
      static ProgressHudState of(BuildContext context) {
        return context.ancestorStateOfType(const TypeMatcher<ProgressHudState>());
      }
    
      ...
    }
    复制代码

    3. 创建HUD

    Widget _createHudView(Widget child) {
      return Stack(
        children: <Widget>[
          // 如果不想屏蔽用户操作,ignoring设置为true,这里设置为无法响应
          IgnorePointer(
            ignoring: false,
            child: Container(
              color: Colors.transparent,
               double.infinity,
              height: double.infinity,
            ),
          ),        
          Center(
            child: Container(
              // 这里设置一定的偏移,因为iPhoneX有下方安全区域,看起来会偏下
              margin: EdgeInsets.fromLTRB(10, 10, 10, 10 - widget.offsetY * 2),
              decoration: BoxDecoration(
                color: Color.fromARGB(255, 33, 33, 33), 
                borderRadius: BorderRadius.circular(5)
              ),
              // 设置最小宽高,如果文字比较多,可以自适应
              constraints: BoxConstraints(
                minHeight: 130,
                minWidth: 130
              ),          
              child: Padding(
                padding: EdgeInsets.all(12),
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    Container(
                      padding: EdgeInsets.all(15),
                      child: child,
                    ),
                    Container(
                      child: Text(
                        _text, 
                        textAlign: TextAlign.center,
                        style: TextStyle(color: Colors.white, fontSize: 16)
                      ),
                    )
                  ],
                ),
              ),
            ),
          ),
        ],
      );
    }
    复制代码

    4. 环形进度

    通过Painter画两个圆

    import 'dart:math';
    import 'package:flutter/material.dart';
    
    
    class CircleProgressBarPainter extends CustomPainter {
      final double progress;
      final double strokeWidth;
      final Color color;
      final Color fillColor;
      const CircleProgressBarPainter({
        this.progress = 0, 
        this.strokeWidth = 3,
        this.color = Colors.grey,
        this.fillColor = Colors.white
      });
    
      @override
      void paint(Canvas canvas, Size size) {
        final paint = new Paint()
          ..color = this.color
          ..style = PaintingStyle.stroke
          ..strokeWidth = strokeWidth;
        final double diam = min(size.width, size.height);
        final centerX = size.width * 0.5;
        final centerY = size.height * 0.5;
        final radius = diam / 2.0;
        
        canvas.drawCircle(Offset(centerX, centerY), radius, paint);
        paint.color = this.fillColor;
        // draw in center
        var rect = Rect.fromLTWH((size.width - diam) * 0.5, 0, diam, diam);
        canvas.drawArc(rect, -0.5 * pi, progress * 2 * pi, false, paint);
      }
    
      @override
      bool shouldRepaint(CustomPainter oldDelegate) => false;
    }
    复制代码

    完整代码见这里

  • 相关阅读:
    Gym102501G Swapping Places(拓扑排序)
    2019SWERC题解
    CF364D Ghd(随机化)
    CF500E New Year Domino(并查集+栈)
    CF280C Game on Tree(期望)
    CF1093G Multidimensional Queries(线段树)
    CF677D Vanya and Treasure(最短路)
    CF788C The Great Mixing(最短路)
    queryset高级用法:prefetch_related
    queryset高级用法:select_related
  • 原文地址:https://www.cnblogs.com/twodog/p/12134891.html
Copyright © 2011-2022 走看看