Flutter——封装一个方便使用的Loading弹窗

2,414 阅读1分钟

前言

之前框架使用的是方式有两种:

1、在根布局中使用stack 如下:
 return Stack(
 		children:[
       	(...),
           loadingWidget(),
       ]
   );

通过visible或者offstage进行包裹,并控制显示。

2、使用showDialog
	showDialog(
   	builder:(ctx)=>loadingWidget();
   )

方案1 图层多了一层,展示效果不灵活。  
方案2 开关不好控制。

之后决定再尝试一下方案3,具体实现如下:

实现

LoadingProgress

增加一个LoadingProgress页面

class LoadingProgress extends StatefulWidget{
  final Widget progress;
  final Color bgColor;
  final DialogLoadingController controller;

  const LoadingProgress({Key key, this.progress,
    this.bgColor,@required this.controller })
      : super(key: key);


  @override
  State<StatefulWidget> createState() {
    return LoadingProgressState();
  }

}

class LoadingProgressState extends BaseState<LoadingProgress> {

  @override
  void initState() {
    super.initState();
	//对controller进行监听
    widget.controller.addListener(() {
      if(widget.controller.isShow){
        //todo
      }else{
        WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
          Navigator.of(context).pop();
        });
      }
    });
  }

  @override
  void dispose() {
    widget.controller.isShow = false;
    widget.controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {

    final size = MediaQuery.of(context).size;

    return Container(
      color: widget.bgColor??Color.fromRGBO(34, 34, 34, 0.3),
      width: size.width,height: size.height,
      alignment: Alignment.center,
      child:widget.progress?? DoubleCircleLoadingWidget(),
    );
  }
}


很简单的代码

DialogLoadingController

之后我们增加一个controller用于控制loading的显隐,这样后续还可以拓展其他功能

class DialogLoadingController extends ChangeNotifier{
  bool isShow = true;
  dismissDialog(){
    isShow = false;
    notifyListeners();
  }
}

ok,功能完成了,下面加到baseState里(我们自己对state的封装)。

加入功能

  DialogLoadingController _dialogLoadingController;

  showProgressDialog({Widget progress,
    Color bgColor,}){
    if(_dialogLoadingController == null){
      _dialogLoadingController = DialogLoadingController();
      Navigator.of(context).push(PageRouteBuilder(
          opaque: false,
          pageBuilder: (ctx,animation,secondAnimation){
            return LoadingProgress(controller: _dialogLoadingController,
              progress: progress,bgColor: bgColor,);
          }
      ));
    }

  }

  dismissProgressDialog(){
    _dialogLoadingController?.dismissDialog();
    _dialogLoadingController = null;
  }

这样,我们在当前页面就可以随时随地的调用

showProgressDialog()
dismissProgressDialog()

进行全屏的loading弹窗显示了。

谢谢大家阅读,有不足的地方欢迎大家指出,如果有更好的实现方式也请告诉我。 :)

Bedrock 框架

目前该功能已加入框架内。

Bedrock 快速开发框架