基础组件库
 
 
 
 
 

252 lines
7.6 KiB

  1. import 'package:event_bus/event_bus.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:pull_to_refresh/pull_to_refresh.dart';
  4. import 'package:provider/provider.dart';
  5. import 'package:flutter_bloc/flutter_bloc.dart';
  6. import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_notifier.dart';
  7. import 'package:zhiying_base_widget/widgets/empty/empty_widget.dart';
  8. import 'package:zhiying_base_widget/widgets/home/home_auth/home_auth.dart';
  9. import 'package:zhiying_base_widget/widgets/refresh/refresh_header/refresh_gif_header.dart';
  10. import 'package:zhiying_comm/zhiying_comm.dart';
  11. import 'bloc/custom_item_page_bloc.dart';
  12. import 'bloc/custom_item_page_state.dart';
  13. import 'bloc/custom_item_page_event.dart';
  14. import 'bloc/custom_item_page_repository.dart';
  15. ///
  16. /// 通用模块的分类导航下的子模块
  17. ///
  18. ///
  19. class CustomItemPage extends StatelessWidget {
  20. final Map<String, dynamic> data;
  21. final int tabIndex;
  22. final String modPid;
  23. final String modId;
  24. final bool needBuildStatus;
  25. Function(double) scroller;
  26. CustomItemPage(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus, {this.scroller});
  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,scroller: this.scroller,),
  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. final Function(double) scroller;
  47. const _CustomItemPageContainer(this.data, this.tabIndex, this.modId, this.modPid, this.needBuildStatus, {this.scroller, Key key}) : super(key: key);
  48. @override
  49. __CustomItemPageContainerState createState() => __CustomItemPageContainerState();
  50. }
  51. class __CustomItemPageContainerState extends State<_CustomItemPageContainer> with AutomaticKeepAliveClientMixin {
  52. @override
  53. bool get wantKeepAlive => true;
  54. ScrollController _controller;
  55. RefreshController _refreshController;
  56. final EventBus _eventBus = EventBus();
  57. /// 回到顶点
  58. void _scrollTop() {
  59. // _controller.jumpTo(0);
  60. _controller.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.linear);
  61. }
  62. /// 初始化
  63. void _initEvent() {
  64. BlocProvider.of<CustomItemPageBloc>(context).add(CustomItemPageInitEvent());
  65. }
  66. /// 刷新
  67. void _refreshEvent() {
  68. BlocProvider.of<CustomItemPageBloc>(context).add(CustomItemPageRefreshEvent());
  69. }
  70. /// 下拉更多
  71. void _loadEvent() {
  72. // BlocProvider.of<CustomItemPageBloc>(context).add(CustomItemPageLoadEvent());
  73. Provider.of<MainPageNotifier>(context, listen: false).loadMore();
  74. Future.delayed(Duration(milliseconds: 500), () => _refreshController?.loadComplete());
  75. }
  76. @override
  77. void initState() {
  78. _controller = ScrollController();
  79. _refreshController = RefreshController(initialRefresh: false);
  80. _initEvent();_controller.addListener(() {
  81. print(_controller.offset.toString());
  82. if(widget.scroller!=null){
  83. widget?.scroller(_controller.offset);
  84. }
  85. });
  86. super.initState();
  87. }
  88. @override
  89. void dispose() {
  90. _controller?.dispose();
  91. _refreshController?.dispose();
  92. super.dispose();
  93. }
  94. @override
  95. Widget build(BuildContext context) {
  96. return BlocConsumer<CustomItemPageBloc, CustomItemPageState>(
  97. listener: (context, state) {},
  98. buildWhen: (prev, current) {
  99. if (current is CustomItemPageRefreshSuccessState) {
  100. _refreshController?.refreshCompleted(resetFooterState: true);
  101. return false;
  102. }
  103. if (current is CustomItemPageRefreshErrorState) {
  104. _refreshController?.refreshFailed();
  105. return false;
  106. }
  107. if (current is CustomItemPageLoadSuccessState) {
  108. _refreshController?.loadComplete();
  109. return false;
  110. }
  111. if (current is CustomItemPageLoadErrorState) {
  112. _refreshController?.loadNoData();
  113. return false;
  114. }
  115. if (current is CustomItemPageErrorState) {
  116. return false;
  117. }
  118. return true;
  119. },
  120. builder: (context, state) {
  121. if (state is CustomItemPageLoadedState) {
  122. if (EmptyUtil.isEmpty(state.model))
  123. return _buildEmptyWidget();
  124. else
  125. return _buildMainWidget(state.model);
  126. }
  127. if (state is CustomItemPageInitErrorState) {
  128. return _buildEmptyWidget();
  129. }
  130. return _buildSkeletonWidget();
  131. },
  132. );
  133. }
  134. /// 有数据
  135. Widget _buildMainWidget(final List<Map<String, dynamic>> model) {
  136. return MediaQuery.removePadding(
  137. context: context,
  138. removeTop: false,
  139. child: Stack(
  140. children: <Widget>[
  141. SmartRefresher(
  142. controller: _refreshController,
  143. enablePullDown: true,
  144. enablePullUp: true,
  145. onRefresh: _refreshEvent,
  146. onLoading: _loadEvent,
  147. header: RefreshGifHeader(),
  148. // footer: RefreshFooter(),
  149. child: CustomScrollView(
  150. controller: _controller,
  151. slivers: _buildContentWidgets(model),
  152. ),
  153. ),
  154. Align(
  155. alignment: Alignment.bottomCenter,
  156. child: Container(
  157. margin: const EdgeInsets.only(bottom: 8),
  158. child: _buildAuthWidget(model),
  159. ), //_buildAuthWidget(model),
  160. )
  161. ],
  162. ),
  163. );
  164. }
  165. /// 根据widget的modName生成视图
  166. List<Widget> _buildContentWidgets(final List<Map<String, dynamic>> datas) {
  167. List<Widget> result = [];
  168. for (int i = 0; i < datas.length; i++) {
  169. WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));
  170. if (item.modName == 'audit_tip') {
  171. Logger.debug('授权组件,跳过');
  172. continue;
  173. }
  174. if (item.modName == 'product') {
  175. datas[i]['eventBus'] = _eventBus;
  176. }
  177. result.addAll(WidgetFactory.create(
  178. item.modName,
  179. isSliver: true,
  180. model: datas[i],
  181. ));
  182. }
  183. // if (widget.needBuildStatus) {
  184. // double top = MediaQueryData.fromWindow(window).padding.top;
  185. // result.insert(
  186. // 0,
  187. // SliverPersistentHeader(
  188. // pinned: false,
  189. // floating: false,
  190. // delegate: CustomSliverPersistentHeaderDelegate(max: top, min: top, child: Container(
  191. // // color: Colors.yellow,
  192. // color: HexColor.fromHex('#FFFF4242'),
  193. // )),
  194. // ));
  195. //
  196. // }
  197. return result;
  198. }
  199. /// 空数据
  200. Widget _buildEmptyWidget() {
  201. return SmartRefresher(
  202. controller: _refreshController,
  203. onRefresh: _refreshEvent,
  204. enablePullDown: true,
  205. child: Container(
  206. child: EmptyWidget(),
  207. ),
  208. );
  209. }
  210. /// 骨架图
  211. Widget _buildSkeletonWidget() {
  212. return Container();
  213. }
  214. /// 特殊的授权组件
  215. Widget _buildAuthWidget(final List<Map<String, dynamic>> datas) {
  216. int length = datas?.length ?? 0;
  217. if (length == 0) return Container();
  218. Widget rlt;
  219. for (int i = 0; i < datas.length; i++) {
  220. WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));
  221. if (item.modName == 'audit_tip') {
  222. rlt = HomeAuth(datas[i]);
  223. break;
  224. }
  225. }
  226. return rlt ?? Container();
  227. }
  228. }