123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- import 'package:cs_resources/generated/assets.dart';
- import 'package:flutter/material.dart';
- import 'package:get/get.dart';
- import 'package:cs_resources/constants/color_constants.dart';
- import 'my_load_image.dart';
- import 'my_text_view.dart';
- ///四种视图状态
- enum LoadState { State_Success, State_Error, State_Loading, State_Empty }
- ///根据不同状态来展示不同的视图
- class LoadStateLayout extends StatefulWidget {
- final LoadState state; //页面状态
- final Widget? successWidget; //成功视图
- final List<Widget>? successSliverWidget; //成功的滚动视图(Sliver的布局)
- final VoidCallback? errorRetry; //错误事件处理
- final Color? themeColor;
- String? errorMessage;
- LoadStateLayout({
- Key? key,
- this.state = LoadState.State_Loading, //默认为加载状态
- this.successWidget, //成功的布局 (二选一)
- this.successSliverWidget, //成功的滚动布局(二选一)
- this.errorMessage, //错误的信息展示
- this.errorRetry, //错误重试的事件
- this.themeColor, //主题颜色,Loading,文本颜色
- }) : super(key: key);
- @override
- _LoadStateLayoutState createState() => _LoadStateLayoutState();
- }
- class _LoadStateLayoutState extends State<LoadStateLayout> {
- @override
- Widget build(BuildContext context) {
- if (widget.successSliverWidget != null) {
- //如果有 successSliverWidget 就使用 Slivers 的方式布局
- return CustomScrollView(
- slivers: _buildSlivers(),
- );
- } else {
- //如果没有有 successSliverWidget 就使用默认布局的方式布局
- return SizedBox(
- width: double.infinity,
- height: double.infinity,
- child: _buildWidget,
- );
- }
- }
- //Slivers的布局
- List<Widget> _buildSlivers() {
- return _buildListWidget;
- }
- ///根据不同状态来显示不同的视图 (默认布局)
- Widget get _buildWidget {
- switch (widget.state) {
- case LoadState.State_Success:
- return widget.successWidget ?? const SizedBox();
- case LoadState.State_Error:
- return _errorView;
- case LoadState.State_Loading:
- return _loadingView;
- case LoadState.State_Empty:
- return _emptyView;
- default:
- return _loadingView;
- }
- }
- ///根据不同状态来显示不同的视图 (CustomScrollView)
- List<Widget> get _buildListWidget {
- switch (widget.state) {
- case LoadState.State_Success:
- return widget.successSliverWidget != null
- ? widget.successSliverWidget!
- : widget.successWidget != null
- ? [widget.successWidget!]
- : [const SizedBox()];
- case LoadState.State_Error:
- return [widget.successSliverWidget != null ? _warpStateLayout(_errorView) : _errorView];
- case LoadState.State_Loading:
- return [widget.successSliverWidget != null ? _warpStateLayout(_loadingView) : _loadingView];
- case LoadState.State_Empty:
- return [widget.successSliverWidget != null ? _warpStateLayout(_emptyView) : _emptyView];
- default:
- return [widget.successSliverWidget != null ? _warpStateLayout(_loadingView) : _loadingView];
- }
- }
- //如果父布局是 CustomScrollView 则使用 SliverFillViewport 包裹状态布局
- Widget _warpStateLayout(Widget widget) {
- return SliverFillViewport(
- delegate: SliverChildBuilderDelegate(
- (context, index) {
- return widget;
- },
- childCount: 1,
- ),
- );
- }
- // ===================================== 真正的状态布局 ↓ =====================================
- ///加载中视图
- Widget get _loadingView {
- return Container(
- width: double.infinity,
- height: double.infinity,
- alignment: Alignment.center,
- child: Column(
- mainAxisSize: MainAxisSize.max,
- mainAxisAlignment: MainAxisAlignment.center,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- CircularProgressIndicator(
- strokeWidth: 3,
- valueColor: AlwaysStoppedAnimation(widget.themeColor ?? Color(0XFFD6E9F1)),
- ),
- MyTextView(
- 'Loading...'.tr,
- marginTop: 15,
- fontSize: 14,
- textColor: widget.themeColor ?? Color(0XFFD6E9F1),
- )
- ],
- ),
- );
- }
- ///错误视图
- Widget get _errorView {
- return Container(
- width: double.infinity,
- height: double.infinity,
- alignment: Alignment.center,
- padding: const EdgeInsets.only(bottom: 10),
- child: GestureDetector(
- onTap: widget.errorRetry,
- child: Column(
- mainAxisSize: MainAxisSize.max,
- crossAxisAlignment: CrossAxisAlignment.center,
- mainAxisAlignment: MainAxisAlignment.center,
- children: <Widget>[
- const MyAssetImage(Assets.baseServicePageLoadError, width: 141, height: 117.5, fit: BoxFit.contain),
- MyTextView(
- widget.errorMessage ?? 'Data loading failed! Please refresh and try again'.tr,
- marginTop: 18,
- fontSize: 14,
- textColor: widget.themeColor ?? Color(0XFFD6E9F1),
- ),
- ],
- )));
- }
- ///数据为空的视图
- Widget get _emptyView {
- return Container(
- width: double.infinity,
- height: double.infinity,
- alignment: Alignment.center,
- padding: const EdgeInsets.only(bottom: 10),
- child: Column(
- mainAxisSize: MainAxisSize.max,
- crossAxisAlignment: CrossAxisAlignment.center,
- mainAxisAlignment: MainAxisAlignment.center,
- children: <Widget>[
- const MyAssetImage(Assets.baseServicePageNoData, width: 123.5, height: 115.5, fit: BoxFit.contain),
- MyTextView(
- 'There is currently no content available'.tr,
- marginTop: 18,
- fontSize: 14,
- textColor: widget.themeColor ?? Color(0XFFD6E9F1),
- ),
- ],
- ),
- );
- }
- }
|