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(),
    );
  }

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

  //  加载失败
  Widget get _errorView {
    return Center(
        child: Column()
    );
  }
      

完整代码如下:

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,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

使用方法如下:

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

LoadingStateWidget(
  retry: model.getData,
  viewState: model.viewState,
  child: HomePageWidget.bodyWidget(model),
)

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

getData() async {
    
    
  if(viewState == ViewState.error){
    
    
    viewState = ViewState.loading;
    notifyListeners();
  }

  await Future.delayed(Duration(seconds: 5));
  viewState = ViewState.error;
  notifyListeners();
}

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

在这里插入图片描述

在这里插入图片描述


总结

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

猜你喜欢

转载自blog.csdn.net/u010755471/article/details/128186198