Flutter自己實(shí)現(xiàn)一個(gè)ProgressHUD

用慣了iOS的SVProgressHUD,但是在flutter pub上的并沒有找到類似的實(shí)現(xiàn),于是自己實(shí)現(xiàn)一個(gè)

主要實(shí)現(xiàn)四個(gè)基本功能

  • Loading顯示
  • 成功顯示
  • 錯(cuò)誤顯示
  • 進(jìn)度顯示:環(huán)形進(jìn)度條和文字

庫地址

https://pub.dartlang.org/packages/bmprogresshud

dependencies:
  bmprogresshud: ^0.0.2

實(shí)現(xiàn)效果

演示效果
  1. 由于HUD是蓋在視圖上面的,通常是整個(gè)頁面,故考慮直接在目標(biāo)Widget上套一層ProgressHUD
  2. 我們需要在特定的地方獲取ProgressHUD進(jìn)行操作,這個(gè)有點(diǎn)類似Navigator瓢宦,參考Navigator的用法,通過of方法獲得

實(shí)際效果如下

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("加載數(shù)據(jù)"),
          );
        }),
      ),
    )
  );
}

實(shí)現(xiàn)效果

1. 顯示和隱藏漸變

通過屬性opacityAnimationController控制透明度灰羽,當(dāng)透明度為0時(shí)候驮履,通過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(() {
          // 隱藏動(dòng)畫結(jié)束鱼辙,隱藏控件
          _isVisible = false;          
        });
      }
    });
    super.initState();
  }

  ...
}

我們通過動(dòng)畫的執(zhí)行方向控制動(dòng)畫

// 顯示動(dòng)畫
_animation.forward();
setState(() {
  _isVisible = true;
});

// 隱藏動(dòng)畫
_animation.reverse();

2. 通過BuildContext獲得Element樹的ProgressHUD

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

  ...
}

3. 創(chuàng)建HUD

Widget _createHudView(Widget child) {
  return Stack(
    children: <Widget>[
      // 如果不想屏蔽用戶操作,ignoring設(shè)置為true玫镐,這里設(shè)置為無法響應(yīng)
      IgnorePointer(
        ignoring: false,
        child: Container(
          color: Colors.transparent,
          width: double.infinity,
          height: double.infinity,
        ),
      ),        
      Center(
        child: Container(
          // 這里設(shè)置一定的偏移倒戏,因?yàn)閕PhoneX有下方安全區(qū)域,看起來會(huì)偏下
          margin: EdgeInsets.fromLTRB(10, 10, 10, 10 - widget.offsetY * 2),
          decoration: BoxDecoration(
            color: Color.fromARGB(255, 33, 33, 33), 
            borderRadius: BorderRadius.circular(5)
          ),
          // 設(shè)置最小寬高恐似,如果文字比較多杜跷,可以自適應(yīng)
          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. 環(huán)形進(jìn)度

通過Painter畫兩個(gè)圓

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;
}

完整代碼見這里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市矫夷,隨后出現(xiàn)的幾起案子葛闷,更是在濱河造成了極大的恐慌,老刑警劉巖双藕,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淑趾,死亡現(xiàn)場離奇詭異,居然都是意外死亡忧陪,警方通過查閱死者的電腦和手機(jī)扣泊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嘶摊,“玉大人延蟹,你說我怎么就攤上這事∫抖眩” “怎么了阱飘?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蹂空。 經(jīng)常有香客問我,道長果录,這世上最難降的妖魔是什么上枕? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮弱恒,結(jié)果婚禮上辨萍,老公的妹妹穿的比我還像新娘。我一直安慰自己返弹,他們只是感情好锈玉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著义起,像睡著了一般拉背。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上默终,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天椅棺,我揣著相機(jī)與錄音犁罩,去河邊找鬼。 笑死两疚,一個(gè)胖子當(dāng)著我的面吹牛床估,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播诱渤,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼丐巫,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了勺美?” 一聲冷哼從身側(cè)響起递胧,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎励烦,沒想到半個(gè)月后谓着,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坛掠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年赊锚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屉栓。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡舷蒲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出友多,到底是詐尸還是另有隱情牲平,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布域滥,位于F島的核電站纵柿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏启绰。R本人自食惡果不足惜昂儒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望委可。 院中可真熱鬧渊跋,春花似錦、人聲如沸着倾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卡者。三九已至蒿囤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間崇决,已是汗流浹背蟋软。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國打工镶摘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人岳守。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓凄敢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親湿痢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涝缝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353