基础组件库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

256 lines
7.7 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. 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. _eventBus = EventBus();
  80. _refreshController = RefreshController(initialRefresh: false);
  81. _initEvent();_controller.addListener(() {
  82. print(_controller.offset.toString());
  83. if(widget.scroller!=null){
  84. widget?.scroller(_controller.offset);
  85. }
  86. });
  87. super.initState();
  88. }
  89. @override
  90. void dispose() {
  91. _controller?.dispose();
  92. _refreshController?.dispose();
  93. _eventBus?.destroy();
  94. super.dispose();
  95. }
  96. @override
  97. Widget build(BuildContext context) {
  98. return BlocConsumer<CustomItemPageBloc, CustomItemPageState>(
  99. listener: (context, state) {},
  100. buildWhen: (prev, current) {
  101. if (current is CustomItemPageRefreshSuccessState) {
  102. _refreshController?.refreshCompleted(resetFooterState: true);
  103. return false;
  104. }
  105. if (current is CustomItemPageRefreshErrorState) {
  106. _refreshController?.refreshFailed();
  107. return false;
  108. }
  109. if (current is CustomItemPageLoadSuccessState) {
  110. _refreshController?.loadComplete();
  111. return false;
  112. }
  113. if (current is CustomItemPageLoadErrorState) {
  114. _refreshController?.loadNoData();
  115. return false;
  116. }
  117. if (current is CustomItemPageErrorState) {
  118. return false;
  119. }
  120. return true;
  121. },
  122. builder: (context, state) {
  123. if (state is CustomItemPageLoadedState) {
  124. Logger.log('custom item page current state = ' + state?.toString());
  125. if (EmptyUtil.isEmpty(state.model))
  126. return _buildEmptyWidget();
  127. else
  128. return _buildMainWidget(state.model);
  129. }
  130. if (state is CustomItemPageInitErrorState) {
  131. return _buildEmptyWidget();
  132. }
  133. return _buildSkeletonWidget();
  134. },
  135. );
  136. }
  137. /// 有数据
  138. Widget _buildMainWidget(final List<Map<String, dynamic>> model) {
  139. return MediaQuery.removePadding(
  140. context: context,
  141. removeTop: false,
  142. child: Stack(
  143. children: <Widget>[
  144. SmartRefresher(
  145. controller: _refreshController,
  146. enablePullDown: true,
  147. enablePullUp: true,
  148. onRefresh: _refreshEvent,
  149. onLoading: _loadEvent,
  150. header: RefreshGifHeader(),
  151. // footer: RefreshFooter(),
  152. child: CustomScrollView(
  153. physics: BouncingScrollPhysics(),
  154. controller: _controller,
  155. slivers: _buildContentWidgets(model),
  156. ),
  157. ),
  158. Align(
  159. alignment: Alignment.bottomCenter,
  160. child: Container(
  161. margin: const EdgeInsets.only(bottom: 8),
  162. child: _buildAuthWidget(model),
  163. ), //_buildAuthWidget(model),
  164. )
  165. ],
  166. ),
  167. );
  168. }
  169. /// 根据widget的modName生成视图
  170. List<Widget> _buildContentWidgets(final List<Map<String, dynamic>> datas) {
  171. List<Widget> result = [];
  172. for (int i = 0; i < datas.length; i++) {
  173. WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));
  174. if (item.modName == 'audit_tip') {
  175. Logger.debug('授权组件,跳过');
  176. continue;
  177. }
  178. if (item.modName == 'product') {
  179. datas[i]['eventBus'] = _eventBus;
  180. }
  181. result.addAll(WidgetFactory.create(
  182. item.modName,
  183. isSliver: true,
  184. model: datas[i],
  185. ));
  186. }
  187. // if (widget.needBuildStatus) {
  188. // double top = MediaQueryData.fromWindow(window).padding.top;
  189. // result.insert(
  190. // 0,
  191. // SliverPersistentHeader(
  192. // pinned: false,
  193. // floating: false,
  194. // delegate: CustomSliverPersistentHeaderDelegate(max: top, min: top, child: Container(
  195. // // color: Colors.yellow,
  196. // color: HexColor.fromHex('#FFFF4242'),
  197. // )),
  198. // ));
  199. //
  200. // }
  201. return result;
  202. }
  203. /// 空数据
  204. Widget _buildEmptyWidget() {
  205. return SmartRefresher(
  206. controller: _refreshController,
  207. onRefresh: _refreshEvent,
  208. enablePullDown: true,
  209. child: Container(
  210. child: EmptyWidget(),
  211. ),
  212. );
  213. }
  214. /// 骨架图
  215. Widget _buildSkeletonWidget() {
  216. return Container();
  217. }
  218. /// 特殊的授权组件
  219. Widget _buildAuthWidget(final List<Map<String, dynamic>> datas) {
  220. int length = datas?.length ?? 0;
  221. if (length == 0) return Container();
  222. Widget rlt;
  223. for (int i = 0; i < datas.length; i++) {
  224. WidgetModel item = WidgetModel.fromJson(Map<String, dynamic>.from(datas[i]));
  225. if (item.modName == 'audit_tip') {
  226. rlt = HomeAuth(datas[i]);
  227. break;
  228. }
  229. }
  230. return rlt ?? Container();
  231. }
  232. }