我们常常会遇到以下的场景:
页面已打开,首先需要请求网络,此时页面展示加载中的视图;
网络请求完毕之后,会出现以下几种情况:
- 遇到各种问题,出现加载失败的情况,但是又可以重新加载
- 加载完后无数据,需要展示无数据的属兔
- 加载成功,展示需要展示的页面
根据以上场景,我封装了一个自定义组件来满足以上要求
///四种视图状态
enum LoadState { State_Success, State_Error, State_Loading, State_Empty }
///根据不同状态来展示不同的视图
class LoadStateLayout extends StatefulWidget {
final LoadState state; //页面状态
final Widget successWidget;//成功视图
final VoidCallback errorRetry; //错误事件处理
LoadStateLayout(
{Key key,
this.state = LoadState.State_Loading,//默认为加载状态
this.successWidget,
this.errorRetry})
: super(key: key);
@override
_LoadStateLayoutState createState() => _LoadStateLayoutState();
}
class _LoadStateLayoutState extends State<LoadStateLayout> {
@override
Widget build(BuildContext context) {
return Container(
//宽高都充满屏幕剩余空间
width: double.infinity,
height: double.infinity,
child: _buildWidget,
);
}
///根据不同状态来显示不同的视图
Widget get _buildWidget {
switch (widget.state) {
case LoadState.State_Success:
return widget.successWidget;
break;
case LoadState.State_Error:
return _errorView;
break;
case LoadState.State_Loading:
return _loadingView;
break;
case LoadState.State_Empty:
return _emptyView;
break;
default:
return null;
}
}
///加载中视图
Widget get _loadingView {
return Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(color: Colors.transparent),
alignment: Alignment.center,
child: Container(
height: 80,
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Color(0x88000000), borderRadius: BorderRadius.circular(6)),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[CircularProgressIndicator(), Text('正在加载')],
),
),
);
}
///错误视图
Widget get _errorView {
return Container(
width: double.infinity,
height: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset(
'images/img/ic_error_page.png',
height: 80,
width: 100,
),
Text("加载失败,请重试"),
RaisedButton(
color: Color(0xffbc2929),
onPressed: widget.errorRetry,
child: Text(
'重新加载',
style: TextStyle(color: Colors.white),
),
)
],
),
);
}
///数据为空的视图
Widget get _emptyView {
return Container(
width: double.infinity,
height: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset(
'images/img/ic_empty.png',
height: 100,
width: 100,
),
Padding(
padding: EdgeInsets.only(top: 10),
child: Text('暂无数据'),
)
],
),
);
}
}
使用方式
import 'package:flutter/material.dart';
import 'package:sah_flutter/ui/widgets/load_state_layout.dart';
class Test extends StatefulWidget {
@override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
//页面加载状态,默认为加载中
LoadState _layoutState = LoadState.State_Loading;
@override
void initState() {
super.initState();
loadData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('测试LoadStateLayout'),
),
body: LoadStateLayout(
state: _layoutState,
errorRetry: () {
setState(() {
_layoutState = LoadState.State_Loading;
});
loadData();
}, //错误按钮点击过后进行重新加载
successWidget: Center(
child: Text('加载成功'),
),
),
);
}
void loadData() {
//模拟网络请求
Future.delayed(Duration(seconds: 2)).then((_) {
//此为加载结束
setState(() {
//如果加载结束后的数据为空,则状态改为空
_layoutState = LoadState.State_Success;
});
}).catchError((_) {
//此为加载失败
setState(() {
_layoutState = LoadState.State_Error;
});
});
}
}
网友评论