基础组件库
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.
 
 
 
 
 

217 lines
6.7 KiB

  1. import 'dart:async';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_bloc/flutter_bloc.dart';
  4. import 'package:cached_network_image/cached_network_image.dart';
  5. import 'package:zhiying_comm/zhiying_comm.dart';
  6. import 'bloc/bloc.dart';
  7. import 'custom_notice_sk.dart';
  8. ///
  9. /// 公告滚动widget
  10. ///
  11. class CustomNoticeWidget extends StatelessWidget {
  12. final Map<String, dynamic> model;
  13. const CustomNoticeWidget(this.model);
  14. @override
  15. Widget build(BuildContext context) {
  16. return BlocProvider<CustomNoticeBloc>(
  17. create: (_) =>
  18. CustomNoticeBloc(repository: CustomNoticeRepository())
  19. ..add(CustomNoticeInitEvent(model: model)),
  20. child: _CustomNoticeWidgetContainer(),
  21. );
  22. }
  23. }
  24. class _CustomNoticeWidgetContainer extends StatefulWidget {
  25. @override
  26. _CustomNoticeWidgetContainerState createState() => _CustomNoticeWidgetContainerState();
  27. }
  28. class _CustomNoticeWidgetContainerState extends State<_CustomNoticeWidgetContainer> {
  29. /// 子item点击事件
  30. void _itemOnClick(CustomNoticeModel model) {
  31. if (pageIndex == model.listStyle.length) {
  32. pageIndex = 0;
  33. }
  34. print('===== $pageIndex');
  35. NoticeListStyle item = model.listStyle[pageIndex];
  36. _itemJump(item);
  37. }
  38. /// 子item跳转
  39. void _itemJump(NoticeListStyle model) {
  40. print('${model?.contentText}');
  41. RouterUtil.route(model, model.toJson(), context);
  42. }
  43. @override
  44. Widget build(BuildContext context) {
  45. return BlocConsumer<CustomNoticeBloc, CustomNoticeState>(
  46. listener: (context, state) {},
  47. buildWhen: (prev, current) {
  48. return true;
  49. },
  50. builder: (context, state) {
  51. if (state is CustomNoticeLoadedState) {
  52. return _getMainWidget(state?.model);
  53. }
  54. return CustomNoticeSkeleton();
  55. },
  56. );
  57. }
  58. /// 主体页面
  59. Widget _getMainWidget(CustomNoticeModel model) {
  60. return Container(
  61. width: double.infinity,
  62. decoration: BoxDecoration(
  63. color: HexColor.fromHex(model?.bgColor),
  64. //color: Colors.orangeAccent,
  65. borderRadius: BorderRadius.only(
  66. topRight: Radius.circular(ParseUtil.stringParseDouble(model?.topRightRadius, defVal: 7.5)),
  67. topLeft: Radius.circular(ParseUtil.stringParseDouble(model?.topLeftRadius, defVal: 7.5)),
  68. bottomLeft: Radius.circular(ParseUtil.stringParseDouble(model?.bottomLeftRadius, defVal: 7.5)),
  69. bottomRight: Radius.circular(ParseUtil.stringParseDouble(model?.bottomRightRadius, defVal: 7.5)),
  70. )),
  71. margin: EdgeInsets.only(
  72. top: ParseUtil.stringParseDouble(model?.topMargin),
  73. left: ParseUtil.stringParseDouble(model?.leftRightMargin),
  74. right: ParseUtil.stringParseDouble(model?.leftRightMargin)),
  75. padding: EdgeInsets.symmetric(horizontal: 7.5, vertical: 7.5),
  76. child: Container(
  77. decoration: BoxDecoration(borderRadius: BorderRadius.circular(7.5), color: HexColor.fromHex(model?.outsideBgColor ?? '#F6F6F6')),
  78. padding: const EdgeInsets.only(top: 8, bottom: 8, left: 12, right: 8),
  79. width: double.infinity,
  80. child: _getChildWidget(model),
  81. ),
  82. );
  83. }
  84. var pageIndex = 0;
  85. Widget _getChildWidget(CustomNoticeModel model) {
  86. return GestureDetector(
  87. onTap: () => _itemOnClick(model),
  88. behavior: HitTestBehavior.opaque,
  89. child: Row(
  90. children: <Widget>[
  91. /// 图片
  92. // Container(width: 52, height: 13, color: Colors.red),
  93. CachedNetworkImage(
  94. imageUrl: model?.appNameImg ?? '',
  95. width: 52,
  96. ),
  97. const SizedBox(width: 14),
  98. /// 文字
  99. Expanded(
  100. child: Container(
  101. width: double.infinity,
  102. height: 15,
  103. alignment: Alignment.centerLeft,
  104. // color: Colors.yellowAccent,
  105. child: MarqueeWidget(
  106. model?.listStyle?.length ?? 0,
  107. (BuildContext context, int index) {
  108. NoticeListStyle item = model.listStyle[index];
  109. return Align(alignment: Alignment.centerLeft, child: Text('${item?.contentText}', style: TextStyle(color: HexColor.fromHex(model?.textColor), fontSize: 12)));
  110. },
  111. onPageChanged: (index) => pageIndex = index,
  112. ),
  113. ),
  114. ),
  115. const SizedBox(width: 14),
  116. /// 图片
  117. CachedNetworkImage(imageUrl: model?.jumpImg ?? '', height: 18),
  118. // Container(
  119. // width: 18,
  120. // height: 18,
  121. // color: Colors.red,
  122. // ),
  123. ],
  124. ),
  125. );
  126. }
  127. }
  128. // 上下滚动的消息轮播
  129. class MarqueeWidget extends StatefulWidget {
  130. int count; // 子视图数量
  131. IndexedWidgetBuilder itemBuilder; // 子视图构造器
  132. final ValueChanged<int> onPageChanged;
  133. MarqueeWidget(this.count, this.itemBuilder, {this.onPageChanged});
  134. @override
  135. _MarqueeWidgetState createState() => _MarqueeWidgetState();
  136. }
  137. class _MarqueeWidgetState extends State<MarqueeWidget> {
  138. PageController _controller;
  139. Timer _timer;
  140. @override
  141. void initState() {
  142. super.initState();
  143. if (widget.count > 0) {
  144. _controller = PageController();
  145. _timer = Timer.periodic(Duration(seconds: 5), (timer) {
  146. // 如果当前位于最后一页,则直接跳转到第一页,两者内容相同,跳转时视觉上无感知
  147. try {
  148. if (_controller.page.round() >= widget.count) {
  149. _controller.jumpToPage(0);
  150. }
  151. _controller.nextPage(duration: Duration(seconds: 1), curve: Curves.linear);
  152. } catch (e){
  153. _timer?.cancel();
  154. }
  155. });
  156. }
  157. }
  158. @override
  159. Widget build(BuildContext context) {
  160. // return PageView.builder(
  161. // scrollDirection: Axis.vertical,
  162. // controller: _controller,
  163. // itemBuilder: (buildContext, index) {
  164. // if (index < widget.count) {
  165. // return widget.itemBuilder(buildContext, index);
  166. // } else {
  167. // return widget.itemBuilder(buildContext, 0);
  168. // }
  169. // },
  170. // itemCount: widget.count + 1, // 在原数据末尾添加一笔数据(即第一笔数据),用于实现无限循环滚动效果
  171. // );
  172. // }
  173. return PageView.custom(
  174. physics: NeverScrollableScrollPhysics(),
  175. childrenDelegate: SliverChildBuilderDelegate((context, index) {
  176. if (index < widget.count) {
  177. return widget.itemBuilder(context, index);
  178. } else {
  179. return widget.itemBuilder(context, 0);
  180. }
  181. }, childCount: widget.count + 1),
  182. scrollDirection: Axis.vertical,
  183. controller: _controller,
  184. onPageChanged: widget?.onPageChanged,
  185. );
  186. }
  187. @override
  188. void dispose() {
  189. super.dispose();
  190. _controller?.dispose();
  191. _timer?.cancel();
  192. }
  193. }