• flutter 自定义加载中间页 loading 菊花组件的封装


    flutter 自定义加载中间页


    前言

    在日常移动开发中,很多时候需要我们添加一个加载中间页,即加载中,加载失败,加载重试,加载完成等功能,这样可以避免在无网或者弱网情况下,导致无法加载完整UI界面,这样的影响是非常不好的。

    本篇文章将记录如果封装一个统一的加载中间页。


    LoadingStateWidget 封装思路

    在文章开始之前,我们先来写一个枚举,用来定义三个加载状态,即加载中,加载成功,加载失败

    enum ViewState { loading, done, error }

    新建一个 LoadingStateWidget 继承自StatelessWidget ,根据我们的需要的大致需求,我们需要接收一个child,一个当前加载状态,一个返回参数,即加载失败,重新加载的retry 方法。

    final ViewState viewState;
    final VoidCallback retry;
    final Widget child;

    接下来就是业务代码

    1. loading: 加载中需要展示的界面
    2. error: 加载失败需要展示的界面
    3. done:加载成功直接返回child

    我这里加载中,直接使用了系统的转圈组件CircularProgressIndicator,当然,这个组件是可以自定义的哦

    //  加载中
      Widget get _loadingView {
        return const Center(
          child: CircularProgressIndicator(),
        );
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    加载失败的时候需要展示的界面,在这里,一般都会加一个重试的按钮,具体的功能,可以根据需求去绘制界面功能

      //  加载失败
      Widget get _errorView {
        return Center(
            child: Column()
        );
      }
          
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    完整代码如下:

    enum ViewState { loading, done, error }
    
    class LoadingStateWidget extends StatelessWidget {
      final ViewState viewState;
      final VoidCallback retry;
      final Widget child;
    
      const LoadingStateWidget(
          {Key? key,
          this.viewState = ViewState.loading,
          required this.retry,
          required this.child})
          : super(key: key);
    
      
      Widget build(BuildContext context) {
        if (viewState == ViewState.loading) {
          return _loadingView;
        }
        if (viewState == ViewState.error) {
          return _errorView;
        } else {
          return child;
        }
      }
    
    //  加载中
      Widget get _loadingView {
        return const Center(
          child: CircularProgressIndicator(),
        );
      }
      
    
    //  加载失败
      Widget get _errorView {
        return Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Image.asset(
                "assets/images/ic_error.png",
                width: 100,
                height: 100,
              ),
              const Padding(
                padding: EdgeInsets.only(top: 8),
                child: Text(
                  TigerString.net_request_fail,
                  style: TextStyle(
                    fontSize: 18,
                    color: Colors.red,
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.only(
                  top: 8,
                ),
                child: OutlinedButton(
                  onPressed: retry,
                  style: ButtonStyle(
                    backgroundColor: MaterialStateProperty.all(Colors.white),
                    overlayColor: MaterialStateProperty.all(Colors.black12),
                  ),
                  child: const Text(
                    TigerString.reload_again,
                    style: TextStyle(
                      color: Colors.black87,
                    ),
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    使用方法如下:

    传入三个参数,加载的延时任务,当前加载状态,及加载完成后需要展示的child

    LoadingStateWidget(
      retry: model.getData,
      viewState: model.viewState,
      child: HomePageWidget.bodyWidget(model),
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5

    我这里的加载refresh 方法,直接使用的是一个延时加载的模拟方式

    getData() async {
      if(viewState == ViewState.error){
        viewState = ViewState.loading;
        notifyListeners();
      }
    
      await Future.delayed(Duration(seconds: 5));
      viewState = ViewState.error;
      notifyListeners();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    总体内容比较简单,代码量也没有多少,个人觉得没什么值得浪费大量语言来描述,看一下运行结果:

    在这里插入图片描述

    在这里插入图片描述


    总结

    记得之前看到一个大佬说过这么一句话,在flutter 中,只有你使用的widget 够多,就没有完成不了的界面,请问你是怎么看待这句话呢?评论区告诉我哦!!!

  • 相关阅读:
    MySQL——基础50题
    Unity - BRP管线关闭 - UpdateDepthTexture的绘制
    基于51单片机的智能台灯设计
    你想要的龙年特效来了
    hosts文件的使用以及修改
    G-TAD: Sub-Graph Localization for Temporal Action Detection 论文阅读笔记
    pandas 排序方法: sort_index(),sort_values()
    大数据之就业岗位
    进程线程知识之线程同步
    ArgoCD技术总结待续
  • 原文地址:https://blog.csdn.net/u010755471/article/details/128186198