基础组件库
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 

211 righe
6.2 KiB

  1. import 'package:flutter/material.dart';
  2. import 'package:pull_to_refresh/pull_to_refresh.dart';
  3. import 'package:provider/provider.dart';
  4. import 'package:flutter_bloc/flutter_bloc.dart';
  5. import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_notifier.dart';
  6. import 'package:zhiying_base_widget/widgets/empty/empty_widget.dart';
  7. import 'package:zhiying_base_widget/widgets/refresh/refresh_footer/refresh_footer.dart';
  8. import 'package:zhiying_base_widget/widgets/refresh/refresh_header/refresh_header.dart';
  9. import 'package:zhiying_comm/zhiying_comm.dart';
  10. import 'bloc/custom_item_page_bloc.dart';
  11. import 'bloc/custom_item_page_state.dart';
  12. import 'bloc/custom_item_page_event.dart';
  13. import 'bloc/custom_item_page_repository.dart';
  14. import 'dart:ui';
  15. import 'package:zhiying_comm/util/custom_sliver_persistent_header_delegate.dart';
  16. ///
  17. /// 通用模块的分类导航下的子模块
  18. ///
  19. ///
  20. class CustomItemPage extends StatelessWidget {
  21. final Map<String, dynamic> data;
  22. final int tabIndex;
  23. final String modPid;
  24. final String modId;
  25. final bool needBuildStatus;
  26. CustomItemPage(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus);
  27. @override
  28. Widget build(BuildContext context) {
  29. return MultiProvider(
  30. providers: [
  31. ChangeNotifierProvider.value(value: MainPageNotifier()),
  32. ],
  33. child: BlocProvider<CustomItemPageBloc>(
  34. create: (_) => CustomItemPageBloc(CustomItemPageRepository(this.data, this.tabIndex, this.modId, this.modPid)),
  35. child: _CustomItemPageContainer(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus),
  36. ),
  37. );
  38. }
  39. }
  40. class _CustomItemPageContainer extends StatefulWidget {
  41. final Map<String, dynamic> data;
  42. final int tabIndex;
  43. final String modPid;
  44. final String modId;
  45. final bool needBuildStatus;
  46. const _CustomItemPageContainer(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus, {Key key}) : super(key: key);
  47. @override
  48. __CustomItemPageContainerState createState() => __CustomItemPageContainerState();
  49. }
  50. class __CustomItemPageContainerState extends State<_CustomItemPageContainer> with AutomaticKeepAliveClientMixin {
  51. @override
  52. bool get wantKeepAlive => true;
  53. ScrollController _controller;
  54. RefreshController _refreshController;
  55. /// 回到顶点
  56. void _scrollTop() {
  57. // _controller.jumpTo(0);
  58. _controller.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.linear);
  59. }
  60. /// 初始化
  61. void _initEvent() {
  62. BlocProvider.of<CustomItemPageBloc>(context).add(CustomItemPageInitEvent());
  63. }
  64. /// 刷新
  65. void _refreshEvent() {
  66. BlocProvider.of<CustomItemPageBloc>(context).add(CustomItemPageRefreshEvent());
  67. }
  68. /// 下拉更多
  69. void _loadEvent() {
  70. // BlocProvider.of<CustomItemPageBloc>(context).add(CustomItemPageLoadEvent());
  71. Provider.of<MainPageNotifier>(context, listen: false).loadMore();
  72. Future.delayed(Duration(milliseconds: 500), () => _refreshController?.loadComplete());
  73. }
  74. @override
  75. void initState() {
  76. _controller = ScrollController();
  77. _refreshController = RefreshController(initialRefresh: false);
  78. _initEvent();
  79. super.initState();
  80. }
  81. @override
  82. void dispose() {
  83. _controller?.dispose();
  84. _refreshController?.dispose();
  85. super.dispose();
  86. }
  87. @override
  88. Widget build(BuildContext context) {
  89. return BlocConsumer<CustomItemPageBloc, CustomItemPageState>(
  90. listener: (context, state) {},
  91. buildWhen: (prev, current) {
  92. if (current is CustomItemPageRefreshSuccessState) {
  93. _refreshController?.refreshCompleted(resetFooterState: true);
  94. return false;
  95. }
  96. if (current is CustomItemPageRefreshErrorState) {
  97. _refreshController?.refreshFailed();
  98. return false;
  99. }
  100. if (current is CustomItemPageLoadSuccessState) {
  101. _refreshController?.loadComplete();
  102. return false;
  103. }
  104. if (current is CustomItemPageLoadErrorState) {
  105. _refreshController?.loadNoData();
  106. return false;
  107. }
  108. if (current is CustomItemPageErrorState) {
  109. return false;
  110. }
  111. return true;
  112. },
  113. builder: (context, state) {
  114. if (state is CustomItemPageLoadedState) {
  115. if (EmptyUtil.isEmpty(state.model))
  116. return _buildEmptyWidget();
  117. else
  118. return _buildMainWidget(state.model);
  119. }
  120. if (state is CustomItemPageInitErrorState) {
  121. return _buildEmptyWidget();
  122. }
  123. return _buildSkeletonWidget();
  124. },
  125. );
  126. }
  127. /// 有数据
  128. Widget _buildMainWidget(final List<Map<String, dynamic>> model) {
  129. return MediaQuery.removePadding(
  130. context: context,
  131. removeTop: false,
  132. child: SmartRefresher(
  133. controller: _refreshController,
  134. enablePullDown: true,
  135. enablePullUp: true,
  136. onRefresh: _refreshEvent,
  137. onLoading: _loadEvent,
  138. header: RefreshHeader(),
  139. // footer: RefreshFooter(),
  140. child: CustomScrollView(
  141. controller: _controller,
  142. slivers: _buildContentWidgets(model),
  143. ),
  144. ),
  145. );
  146. }
  147. /// 根据widget的modName生成视图
  148. List<Widget> _buildContentWidgets(final List<Map<String, dynamic>> datas) {
  149. List<Widget> result = [];
  150. for (int i = 0; i < datas.length; i++) {
  151. WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));
  152. result.addAll(WidgetFactory.create(
  153. item.modName,
  154. isSliver: true,
  155. model: datas[i],
  156. ));
  157. }
  158. if (widget.needBuildStatus) {
  159. double top = MediaQueryData.fromWindow(window).padding.top;
  160. result.insert(
  161. 0,
  162. SliverPersistentHeader(
  163. pinned: true,
  164. floating: false,
  165. delegate: CustomSliverPersistentHeaderDelegate(max: top, min: top, child: Container(
  166. // color: Colors.yellow,
  167. color: HexColor.fromHex('#FFFF4242'),
  168. )),
  169. ));
  170. }
  171. return result;
  172. }
  173. /// 空数据
  174. Widget _buildEmptyWidget() {
  175. return SmartRefresher(
  176. controller: _refreshController,
  177. onRefresh: _refreshEvent,
  178. enablePullDown: true,
  179. child: Container(
  180. child: EmptyWidget(),
  181. ),
  182. );
  183. }
  184. /// 骨架图
  185. Widget _buildSkeletonWidget() {
  186. return Container();
  187. }
  188. }