基础组件库
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 

419 行
14 KiB

  1. import 'dart:typed_data';
  2. import 'dart:ui' as ui;
  3. import 'package:flutter/cupertino.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:flutter/rendering.dart';
  6. import 'package:flutter/services.dart';
  7. import 'package:flutter_swiper/flutter_swiper.dart';
  8. import 'package:fluttertoast/fluttertoast.dart';
  9. import 'package:zhiying_base_widget/pages/invited_friends/invited_friends_bloc.dart';
  10. import 'package:zhiying_base_widget/pages/invited_friends/models/invite_friend_data_model.dart';
  11. import 'package:zhiying_base_widget/pages/invited_friends/models/invited_friends_model.dart';
  12. import 'package:zhiying_base_widget/template/invited_friend_template/invited_friend_template_creater.dart';
  13. import 'package:zhiying_base_widget/template/invited_friend_template/inviter_friend_template.dart';
  14. import 'package:zhiying_base_widget/widgets/empty/empty_widget.dart';
  15. import 'package:zhiying_base_widget/widgets/share/models/share_data_model.dart';
  16. import 'package:zhiying_base_widget/widgets/share/share_alert.dart';
  17. import 'package:zhiying_comm/util/base_bloc.dart';
  18. import 'package:zhiying_comm/zhiying_comm.dart';
  19. // 邀请好友
  20. class InvitedFriendsPage extends StatefulWidget {
  21. final Map<String, dynamic> model;
  22. const InvitedFriendsPage(this.model, {Key key}) : super(key: key);
  23. @override
  24. _InvitedFriendsPageState createState() => _InvitedFriendsPageState();
  25. }
  26. class _InvitedFriendsPageState extends State<InvitedFriendsPage> {
  27. @override
  28. Widget build(BuildContext context) {
  29. return BlocProvider<InvitedFriendshBloc>(
  30. bloc: InvitedFriendshBloc(),
  31. child: _InvitedFriendsContainer(widget.model),
  32. );
  33. }
  34. }
  35. class _InvitedFriendsContainer extends StatefulWidget {
  36. final Map<String, dynamic> data;
  37. const _InvitedFriendsContainer(this.data, {Key key}) : super(key: key);
  38. @override
  39. _InvitedFriendsContainerState createState() =>
  40. _InvitedFriendsContainerState();
  41. }
  42. class _InvitedFriendsContainerState extends State<_InvitedFriendsContainer> {
  43. InvitedFriendshBloc _bloc;
  44. InvitedFriendsModel _model;
  45. int _currentIndex = 0; // 邀请海报下标
  46. List<GlobalKey> _contentKeys;
  47. @override
  48. void initState() {
  49. _bloc = BlocProvider.of<InvitedFriendshBloc>(context);
  50. _bloc.loadData(widget.data['skip_identifier']);
  51. super.initState();
  52. }
  53. @override
  54. Widget build(BuildContext context) {
  55. return StreamBuilder<InvitedFriendsModel>(
  56. stream: _bloc.outData,
  57. builder: (BuildContext context, AsyncSnapshot snapshot) {
  58. _model = snapshot.data;
  59. _contentKeys = List.generate(
  60. _model?.dataModel?.posterList?.length ?? 0,
  61. (index) => GlobalKey());
  62. var posters = List.generate(
  63. _model?.dataModel?.posterList?.length ?? 0, (index) {
  64. return InvitedFriendsTemp(
  65. _model.dataModel.posterList[index], _contentKeys[index]);
  66. });
  67. return Scaffold(
  68. appBar: _createNav(),
  69. body: _model == null
  70. ? Container()
  71. : Stack(
  72. children: <Widget>[
  73. Container(
  74. width: double.infinity,
  75. height: double.infinity,
  76. child: CachedNetworkImage(
  77. imageUrl: _model?.bgImg ?? '',
  78. fit: BoxFit.cover,
  79. ),
  80. ),
  81. Column(
  82. children: <Widget>[
  83. Expanded(
  84. child: _createSwiper(posters),
  85. ),
  86. _createTeacher(),
  87. _createBottom(),
  88. ],
  89. ),
  90. ],
  91. ),
  92. );
  93. });
  94. }
  95. // 导航栏
  96. Widget _createNav() {
  97. return CupertinoNavigationBar(
  98. border: Border(
  99. bottom: BorderSide(
  100. width: 0.0, // One physical pixel.
  101. style: BorderStyle.none,
  102. ),
  103. ),
  104. backgroundColor: HexColor.fromHex(_model?.appBarBgColor ?? '#ffffff'),
  105. leading: Navigator.canPop(context)
  106. ? GestureDetector(
  107. child: Container(
  108. padding: EdgeInsets.zero,
  109. child: Icon(
  110. Icons.arrow_back_ios,
  111. size: 20,
  112. ),
  113. ),
  114. onTap: () {
  115. if (Navigator.canPop(context)) {
  116. Navigator.pop(context);
  117. }
  118. },
  119. )
  120. : Container(),
  121. middle: Text(
  122. _model?.appBarName ?? '邀请好友',
  123. style: TextStyle(
  124. fontSize: 15,
  125. color: HexColor.fromHex(_model?.appBarNameColor ?? '#333333'),
  126. ),
  127. ),
  128. trailing: Text(
  129. _model?.appBarRightBtnText ?? '规则',
  130. style: TextStyle(
  131. fontSize: 15,
  132. color: HexColor.fromHex(_model?.appBarRightBtnTextColor ?? '#333333'),
  133. ),
  134. ),
  135. );
  136. }
  137. Widget _createSwiper(List<Widget> posters) {
  138. if ((_model?.dataModel?.posterList?.length ?? 0) <= 0) {
  139. return Container(
  140. margin: EdgeInsets.only(left: 20, right: 20, top: 20, bottom: 20),
  141. width: double.infinity,
  142. child: EmptyWidget(),
  143. color: Colors.white,
  144. );
  145. }
  146. return Container(
  147. width: double.infinity,
  148. child: Swiper(
  149. onIndexChanged: (index) {
  150. _currentIndex = index;
  151. },
  152. itemBuilder: (BuildContext context, int index) {
  153. return posters[index];
  154. },
  155. itemCount: posters.length,
  156. viewportFraction: 0.7,
  157. scale: 0.9,
  158. ),
  159. );
  160. }
  161. Widget _createTeacher() {
  162. if (_model.wechatTip == null) {
  163. return Container();
  164. }
  165. InvitedWechatTeacherSkipModel skipModel;
  166. // 是否绑定微信导师
  167. if (_model.dataModel.isBindTeacher == '1') {
  168. skipModel = _model.wechatTip.toWechatTeacher;
  169. } else {
  170. skipModel = _model.wechatTip.toInputWechatUsername;
  171. }
  172. return Container(
  173. width: double.infinity,
  174. margin: EdgeInsets.only(top: 20, left: 30, right: 30),
  175. padding: EdgeInsets.only(left: 13, right: 3),
  176. height: 36,
  177. decoration: BoxDecoration(
  178. color: Color(0x80ffffff),
  179. borderRadius: BorderRadius.circular(18),
  180. ),
  181. child: Row(
  182. children: <Widget>[
  183. Container(
  184. margin: EdgeInsets.only(right: 10),
  185. width: 18,
  186. height: 18,
  187. child:
  188. CachedNetworkImage(imageUrl: _model?.wechatTip?.icon ?? '')),
  189. Expanded(
  190. child: Text(
  191. skipModel.tipText ?? '',
  192. maxLines: 1,
  193. overflow: TextOverflow.ellipsis,
  194. style: TextStyle(
  195. fontSize: 13,
  196. color: HexColor.fromHex(skipModel.tipTextColor ?? '#333333'),
  197. ),
  198. ),
  199. ),
  200. GestureDetector(
  201. onTap: () {
  202. RouterUtil.route(skipModel, skipModel.toJson(), context);
  203. },
  204. child: Container(
  205. width: 88,
  206. height: 30,
  207. decoration: BoxDecoration(
  208. color: HexColor.fromHex(
  209. _model?.wechatTip?.btnBgColor ?? '#ffffff'),
  210. borderRadius: BorderRadius.circular(15)),
  211. child: Center(
  212. child: Text(
  213. skipModel?.btnText ?? '',
  214. style: TextStyle(
  215. fontSize: 13,
  216. color: HexColor.fromHex(
  217. _model?.wechatTip?.btnTextColor ?? '#333333'),
  218. ),
  219. ),
  220. ),
  221. ),
  222. ),
  223. ],
  224. ),
  225. );
  226. }
  227. Widget _createBottom() {
  228. return SafeArea(
  229. top: false,
  230. child: Container(
  231. margin: EdgeInsets.all(12.5),
  232. padding: EdgeInsets.all(10),
  233. width: double.infinity,
  234. decoration: BoxDecoration(
  235. color: HexColor.fromHex(_model?.bottom?.bgColor ?? '#ffffff'),
  236. borderRadius: BorderRadius.circular(18),
  237. boxShadow: [
  238. BoxShadow(
  239. offset: Offset(0, 5), //x,y轴
  240. color: Colors.black12.withOpacity(0.1), //投影颜色
  241. blurRadius: 10 //,投影距离
  242. )
  243. ],
  244. ),
  245. child: Column(
  246. children: <Widget>[
  247. Row(
  248. children:
  249. List.generate(_model?.bottom?.btns?.length ?? 0, (index) {
  250. InvitedFriendsButtonModel model = _model.bottom.btns[index];
  251. return Expanded(
  252. child: GestureDetector(
  253. onTap: () {
  254. _onButtonTap(model.type ?? '');
  255. },
  256. child: Container(
  257. margin: EdgeInsets.only(left: 8, right: 8),
  258. height: 28,
  259. decoration: BoxDecoration(
  260. color: HexColor.fromHex(model?.bgColor ?? ''),
  261. borderRadius: BorderRadius.circular(14),
  262. ),
  263. child: Row(
  264. mainAxisAlignment: MainAxisAlignment.center,
  265. crossAxisAlignment: CrossAxisAlignment.center,
  266. children: <Widget>[
  267. Container(
  268. margin: EdgeInsets.only(right: 2),
  269. width: 12,
  270. height: 12,
  271. child: CachedNetworkImage(
  272. imageUrl: model?.icon ?? '',
  273. ),
  274. ),
  275. Text(
  276. model?.text,
  277. style: TextStyle(
  278. color: HexColor.fromHex(
  279. model?.textColor ?? '#ffffff'),
  280. fontSize: 13),
  281. ),
  282. ],
  283. ),
  284. ),
  285. ),
  286. );
  287. }),
  288. ),
  289. _model?.bottom?.tipText == null || _model?.bottom?.tipText == ''
  290. ? Container()
  291. : Padding(
  292. padding: EdgeInsets.only(top: 10),
  293. child: Text(
  294. _model?.bottom?.tipText ?? '',
  295. style: TextStyle(
  296. fontSize: 13,
  297. color: HexColor.fromHex(
  298. _model?.bottom?.tipTextColor ?? '#999999')),
  299. ),
  300. ),
  301. ],
  302. ),
  303. ),
  304. );
  305. }
  306. // 底部按钮点击
  307. void _onButtonTap(String type) {
  308. if (_currentIndex >= (_model?.dataModel?.posterList?.length ?? 0)) {
  309. Fluttertoast.showToast(msg: '分享失败,暂无选中海报');
  310. return;
  311. }
  312. InvitedFriendsPosterDataModel poster =
  313. _model.dataModel.posterList[_currentIndex];
  314. if (type == 'copy_link') {
  315. //复制链接
  316. if (_model?.dataModel?.inviteLink != null &&
  317. _model.dataModel.inviteLink.length > 0) {
  318. Fluttertoast.showToast(msg: '复制成功');
  319. Clipboard.setData(ClipboardData(text: _model.dataModel.inviteLink));
  320. }
  321. } else if (type == 'share_poster') {
  322. //分享海报
  323. GlobalKey key = _contentKeys[_currentIndex];
  324. _sharePoster(key);
  325. } else if (type == 'copy_invite_code') {
  326. //复制邀请码
  327. if (poster?.inviteCode != null && poster.inviteCode != '') {
  328. Fluttertoast.showToast(msg: '复制成功');
  329. Clipboard.setData(ClipboardData(text: poster.inviteCode));
  330. }
  331. }
  332. }
  333. // 生成海报分享
  334. void _sharePoster(GlobalKey key) async {
  335. BuildContext buildContext = key.currentContext;
  336. if (null != buildContext) {
  337. RenderRepaintBoundary boundary = buildContext.findRenderObject();
  338. ui.Image image = await boundary.toImage(pixelRatio: 2.0);
  339. // 注意:png是压缩后格式,如果需要图片的原始像素数据,请使用rawRgba
  340. ByteData byteData =
  341. await image.toByteData(format: ui.ImageByteFormat.png);
  342. Uint8List pngBytes = byteData.buffer.asUint8List();
  343. ShareDataModel shareModel = ShareDataModel(poster: pngBytes);
  344. _showShareAlert(shareModel);
  345. }
  346. }
  347. // 弹出分享框
  348. void _showShareAlert(ShareDataModel shareModel) async {
  349. showCupertinoModalPopup(
  350. context: context,
  351. builder: (context) => ShareAlert(
  352. shareModel,
  353. 'pub.flutter.share_icon',
  354. // child: GoodsShareAlertContent(),
  355. ),
  356. );
  357. }
  358. }
  359. class InvitedFriendsTemp extends StatefulWidget {
  360. final InvitedFriendsPosterDataModel dataModel;
  361. final GlobalKey contentKey;
  362. const InvitedFriendsTemp(this.dataModel, this.contentKey, {Key key})
  363. : super(key: key);
  364. @override
  365. _InvitedFriendsTempState createState() => _InvitedFriendsTempState();
  366. }
  367. class _InvitedFriendsTempState extends State<InvitedFriendsTemp> {
  368. double _scale = 0;
  369. @override
  370. void initState() {
  371. WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
  372. double scaleW = context.size.height / 667;
  373. double scaleH = context.size.width / 375;
  374. double scale = scaleH < scaleW ? scaleH : scaleW;
  375. if (scale != _scale) {
  376. setState(() {
  377. _scale = scale;
  378. });
  379. }
  380. Logger.debug('${context.size.height} ${context.size.width} ${_scale}');
  381. });
  382. super.initState();
  383. }
  384. @override
  385. Widget build(BuildContext context) {
  386. return Transform.scale(
  387. scale: _scale,
  388. child: InvitedFriendTemplateCreater.create(
  389. widget.dataModel, widget.contentKey));
  390. }
  391. }