Flutter 加載中視圖、失敗視圖、空視圖封裝

效果

實現代碼如下

test.dart

import 'dart:io';
import 'dart:math';
import 'package:com/widget/base_layout.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(MaterialApp(
    debugShowCheckedModeBanner: false,
    home: MyApp(),
  ));
  if (Platform.isAndroid) {
    SystemUiOverlayStyle systemUiOverlayStyle =
    SystemUiOverlayStyle(statusBarColor: Colors.transparent);
    SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
  }
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp>{
  BaseLayoutStatus status = BaseLayoutStatus.none;

  _loadData(){
    setState(() {
      status = BaseLayoutStatus.loading;

    });

    Future.delayed(Duration(seconds: 3),(){
      setState(() {
        switch(Random().nextInt(3)){
          case 0:
            status = BaseLayoutStatus.fail;
            break;
          case 1:
            status = BaseLayoutStatus.nodata;
            break;
          default:
            status = BaseLayoutStatus.success;
            break;
        }
      });
    });

  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text("頁面"),
      ),
      body: BaseLayout(
          layoutType: status,
          callBack: _loadData,
          child: Stack(
            children: <Widget>[
              /*Container(
                decoration: BoxDecoration(
                    image: DecorationImage(
                        image: AssetImage('assets/images/tzd.jpg'),
                        fit: BoxFit.fill)),
              ),*/
              Container(
                width: MediaQuery.of(context).size.width,
                color: Colors.green,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    SizedBox(
                      width: 200.0,
                      height: 50.0,
                      child: RaisedButton(
                        onPressed: () {
                          _loadData();
                        },
                        child: Text('點我'),
                      ),
                    ),
                  ],
                ),
              )
            ],
          ),
      ),
    );
  }
}

base_layout.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

typedef CallBack = void Function();

///包含加載中視圖 失敗視圖 沒有數據視圖 成功視圖
class BaseLayout extends StatefulWidget {
  BaseLayoutStatus layoutType = BaseLayoutStatus.none;
  final Widget child;
  CallBack callBack;
  final double opacity;

  BaseLayout({@required this.layoutType, @required this.child,this.callBack,this.opacity = 0.5,});

  @override
  _BaseLayoutState createState() => _BaseLayoutState();
}

class _BaseLayoutState extends State<BaseLayout>{
  @override
  Widget build(BuildContext context) {
    var widgets = <Widget>[];
    widgets.add(widget.child);
    Widget w;
    switch (this.widget.layoutType) {
      case BaseLayoutStatus.loading:
        w = Stack(
          children: <Widget>[
            Opacity(
              child: ModalBarrier(
                dismissible: false,
                color:Color(0xff0b0b0b),
              ),
              opacity: widget.opacity,
            ),
            Container(
              width: MediaQuery.of(context).size.width,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  CupertinoActivityIndicator(
                    radius: 30.0,
                  ),
                  SizedBox(height: 10,),
                  Text(
                    '努力加載中',
                    style: TextStyle(color: Color(0xffffffff),fontSize: 13),
                  ),
                ],
              ),
            ),
          ],
        );
        widgets.add(w);
        break;
      case BaseLayoutStatus.fail:
        w = Container(
          width: MediaQuery.of(context).size.width,
          color: Color(0xff0b0b0b),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              Image.asset("assets/images/icon_failedtoload.webp",width: 90,height: 90,),
              SizedBox(height: 15,),
              Text(
                '加載失敗',
                style: TextStyle(color: Color(0xff666666),fontSize: 14),
              ),
              SizedBox(height: 10,),
              GestureDetector(
                onTap: (){
                  if(this.widget.callBack!=null)
                    this.widget.callBack();
                },
                child: Text(
                  '重新加載',
                  style: TextStyle(color: Color(0xff3f54d1),fontSize: 14),
                ),
              ),
            ],
          ),
        );
        widgets.add(w);
        break;
      case BaseLayoutStatus.nodata:
        w = Container(
          width: MediaQuery.of(context).size.width,
          color: Color(0xff0b0b0b),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              Image.asset("assets/images/icon_zanwukucun.png",width: 90,height: 90,),
              SizedBox(height: 15,),
              Text(
                '暫時沒有數據',
                style: TextStyle(color: Color(0xff666666),fontSize: 14),
              ),
              SizedBox(height: 10,),
              GestureDetector(
                onTap: (){
                  if(this.widget.callBack!=null)
                    this.widget.callBack();
                },
                child: Text(
                  '刷新',
                  style: TextStyle(color: Color(0xff3f54d1),fontSize: 14),
                ),
              ),
            ],
          ),
        );
        widgets.add(w);
        break;
      case BaseLayoutStatus.success:
      case BaseLayoutStatus.none:
        break;
    }
    return Stack(children: widgets);
  }
}

enum BaseLayoutStatus {
  loading, //加載中視圖
  fail, //失敗視圖
  nodata, //沒有數據視圖
  success, //成功加載數據視圖
  none //沒有狀態
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章