Flutter加载(loading)页面 2023-01-20

2023-01-19  本文已影响0人  勇往直前888

需求简介

一般的页面,大多数可以分为三种状态:

  1. 数据加载完成,正常显示;

  2. 数据加载完成,但是没有数据,一般会有一个空数据视图;
    加载后网络错误一般给个toast提示就好,给个错误视图并没有什么价值。

  3. 加载过程,一般是loading视图,这个就是当前的话题;

简单实现

一般的toast插件,都会提供一个loading视图。比如我们现在用的bot_toast插件,大多数时候用的是toast提示。网络访问时的loading视图用的也是他,而且直接做在底层的request接口。只要有网络访问,就自动显示。

企业微信截图_62fa2228-9bcf-473d-81e1-47bfbb65f5d3.png

自定义视图

如果简单的loading不喜欢,可以考虑自定义写一个。
这里有一个非常好用的插件lottie

他的特点是,先用AE工具做一个动画,然后借助工具Bodymovin转化为json文件。把这个json文件以资源的形式加入工程,然后就可以用这个lottie工具进行展示。

企业微信截图_efb3cd09-06a4-4605-a379-710af219e2fc.png

这样出来的loading动画比直接使用gif文件,质量上要好很多。所以这个插件还是很受欢迎的。

企业微信截图_41311865-2609-4049-9cee-5ef53829f304.png

使用

企业微信截图_26bf171c-189f-49a3-866b-c7e8f51e9d87.png

封装

loading视图

  Widget get _loadingView {
    // return Center(
    //   child: Lottie.network('https://assets3.lottiefiles.com/private_files/lf30_gvdwzaoj.json'),
    // );
    // return Center(child: Lottie.asset("assets/loading.json"));
    return Center(
      child: Container(
        color: Colors.transparent,
        height: ScreenUtil().screenHeight,
        width: ScreenUtil().screenWidth,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              decoration: BoxDecoration(
                color: const Color(0x99000000),
                borderRadius: BorderRadius.all(Radius.circular(5.w)),
              ),
              width: 100.w,
              height: 100.w,
              child: Center(
                child: SizedBox(
                  width: 60.w,
                  height: 60.w,
                  child: Lottie.asset("assets/lottie/loading.json"),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

布局实现

这个loading视图做成了一个公共组件,主要的布局代码如下:

  @override
  Widget build(BuildContext context) {
    if (cover) {
      return Stack(
        children: [child, isLoading ? _loadingView : Container()],
      );
    } else {
      return isLoading ? _loadingView : child;
    }
  }

使用

        body: LottieUtils(
          isLoading: logic.isShowLoading,
          cover: logic.hasData,
          child: buildBody(),
        ),
  /// 加载过程标记
  /// 是否有数据; 根据接口返回的total来判断
  /// 无数据,只显示loading,cover参数为false;
  /// 有数据,loading展示在原有视图之上,cover参数为true;
  bool get hasData {
    return total > 0;
  }

  bool isDataReady = false;
  bool get isShowLoading {
    return !isDataReady;
  }
  /// 获取预演包裹列表; 上拉,下拉,接口封装
  /// 加载过程标记做在这个接口上
  Future getRehearList({bool isRefresh = false}) async {
    /// 接口开始,显示loading
    isDataReady = false;
    update();

    StorageApi.previewItem(
      parameters: queryParams,
      success: (response) {
        /// 成功,隐藏loading
        isDataReady = true;
        update();
       
        /// 其他业务处理代码
          
      },
      fail: (e) {
        /// 失败,隐藏loading
        isDataReady = true;
        update();
      },
    );
  }

全局loading

在大多数情况下,上面的loading方案已经够用。但是,某些特殊情况,就力不从心。
上面的Loading和具体的页面深度绑定,有具体的上下文环境,可以工作很好。
对于那些离开具体上下文全局场景,需要那种浮层式的全局loading。

借用插件

全局浮层写起来麻烦,那么可以考虑借用插件来实现。工程中的toast用的是bot_toast,那么就可以借用这个来实现。

  static showToastLoading() {
    BotToast.showCustomLoading(
      toastBuilder: (cancelFunc) {
        return _loadingView;
      },
    );
  }

  static hideToastLoading() {
    BotToast.closeAllLoading();
  }
  static Widget get _loadingView {
    return Center(
      child: Container(
        color: Colors.transparent,
        height: ScreenUtil().screenHeight,
        width: ScreenUtil().screenWidth,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              decoration: BoxDecoration(
                color: const Color(0x99000000),
                borderRadius: BorderRadius.all(Radius.circular(5.w)),
              ),
              width: 100.w,
              height: 100.w,
              child: Center(
                child: SizedBox(
                  width: 60.w,
                  height: 60.w,
                  child: Lottie.asset("assets/lottie/loading.json"),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
上一篇下一篇

猜你喜欢

热点阅读