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

share_alert.dart 10 KiB

4 年前
4 年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'dart:ui';
  4. import 'package:cached_network_image/cached_network_image.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:fluttertoast/fluttertoast.dart';
  7. import 'package:path_provider/path_provider.dart';
  8. import 'package:permission_handler/permission_handler.dart';
  9. import 'package:share_extend/share_extend.dart';
  10. import 'package:sharesdk_plugin/sharesdk_plugin.dart';
  11. import 'package:zhiying_base_widget/dialog/loading/loading.dart';
  12. import 'package:zhiying_base_widget/utils/image_download_util/image_download_util.dart';
  13. import 'package:zhiying_base_widget/widgets/share/models/share_alert_model.dart';
  14. import 'package:zhiying_base_widget/widgets/share/models/share_data_model.dart';
  15. import 'package:zhiying_base_widget/widgets/share/models/share_icon_model.dart';
  16. import 'package:zhiying_base_widget/widgets/share/share_alert_content.dart';
  17. import 'package:zhiying_comm/zhiying_comm.dart';
  18. class ShareAlert extends StatefulWidget {
  19. final String skipIdentifier;
  20. final bool isContentShow;
  21. final ShareDataModel model;
  22. const ShareAlert(this.model, this.skipIdentifier, {Key key, this.isContentShow = false}) : super(key: key); // 中间视图
  23. @override
  24. _ShareAlertState createState() => _ShareAlertState();
  25. }
  26. class _ShareAlertState extends State<ShareAlert> {
  27. ShareAlertModel _iconModel;
  28. @override
  29. void initState() {
  30. NetUtil.request('/api/v1/mod/${widget.skipIdentifier}', method: NetMethod.GET, onCache: (data) {
  31. _parseData(data);
  32. }, onSuccess: (data) {
  33. _parseData(data);
  34. }, onError: (err) {});
  35. super.initState();
  36. }
  37. void _parseData(Map<String, dynamic> data) {
  38. List modList = data['mod_list'];
  39. Map d = modList.first;
  40. if (d != null) {
  41. String dString = d['data'];
  42. _iconModel = ShareAlertModel.fromJson(Map<String, dynamic>.from(jsonDecode(dString)));
  43. setState(() {});
  44. }
  45. }
  46. @override
  47. Widget build(BuildContext context) {
  48. return WillPopScope(
  49. onWillPop: () async {
  50. Loading.dismiss();
  51. Navigator.canPop(context);
  52. return true;
  53. },
  54. child: GestureDetector(
  55. child: Scaffold(
  56. backgroundColor: Colors.transparent,
  57. body: BackdropFilter(
  58. filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), //背景
  59. child: Container(
  60. child: Column(
  61. children: <Widget>[
  62. Expanded(
  63. child: Center(child: widget.isContentShow ? ShareAlertContent(_iconModel) : Container()),
  64. ),
  65. _ShareAlertContent(widget.model, widget.skipIdentifier, _iconModel),
  66. ],
  67. ),
  68. ), // 模糊化
  69. ),
  70. ),
  71. onTap: () {
  72. Navigator.of(context).pop();
  73. },
  74. ),
  75. );
  76. }
  77. }
  78. class _ShareAlertContent extends StatefulWidget {
  79. final ShareDataModel model;
  80. final String skipIdentifier;
  81. final ShareAlertModel iconModel;
  82. const _ShareAlertContent(this.model, this.skipIdentifier, this.iconModel, {Key key}) : super(key: key);
  83. @override
  84. _ShareAlertContentState createState() => _ShareAlertContentState();
  85. }
  86. class _ShareAlertContentState extends State<_ShareAlertContent> {
  87. @override
  88. Widget build(BuildContext context) {
  89. return GestureDetector(
  90. onTap: () {},
  91. child: Container(
  92. width: double.infinity,
  93. decoration: BoxDecoration(
  94. color: Colors.white,
  95. borderRadius: BorderRadius.only(
  96. topLeft: Radius.circular(12),
  97. topRight: Radius.circular(12),
  98. ),
  99. ),
  100. child: SafeArea(
  101. top: false,
  102. child: Column(
  103. children: <Widget>[
  104. Container(
  105. margin: EdgeInsets.only(top: 8, bottom: 8),
  106. width: 62,
  107. height: 4,
  108. decoration: BoxDecoration(color: Color(0xffd8d8d8), borderRadius: BorderRadius.circular(2)),
  109. ),
  110. Text(
  111. '分享至',
  112. style: TextStyle(fontSize: 15, color: Color(0xff333333), fontWeight: FontWeight.bold),
  113. ),
  114. Container(
  115. margin: EdgeInsets.only(left: 12, right: 12, top: 10, bottom: 10),
  116. child: _createIcons(),
  117. ),
  118. GestureDetector(
  119. child: Container(
  120. margin: EdgeInsets.only(left: 12, right: 12, bottom: 10),
  121. padding: EdgeInsets.all(12),
  122. decoration: BoxDecoration(color: Color(0xfff3f3f3), borderRadius: BorderRadius.circular(8)),
  123. child: Center(
  124. child: Text(
  125. '取消',
  126. style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold, color: Color(0xff999999)),
  127. ),
  128. ),
  129. ),
  130. onTap: () {
  131. Navigator.of(context).pop();
  132. },
  133. )
  134. ],
  135. ),
  136. ),
  137. ),
  138. );
  139. }
  140. Widget _createIcons() {
  141. return Wrap(
  142. spacing: 10,
  143. runSpacing: 10,
  144. children: widget.iconModel?.icons?.map((item) {
  145. return _createIcon(item);
  146. })?.toList() ??
  147. [],
  148. );
  149. }
  150. Widget _createIcon(ShareIconModel item) {
  151. return GestureDetector(
  152. child: Container(
  153. width: 60,
  154. child: Column(
  155. children: <Widget>[
  156. Container(
  157. width: 40,
  158. height: 40,
  159. child: CachedNetworkImage(
  160. imageUrl: item.icon,
  161. fit: BoxFit.contain,
  162. ),
  163. ),
  164. Padding(
  165. padding: const EdgeInsets.only(top: 2, bottom: 2),
  166. child: Text(
  167. item.name,
  168. style: TextStyle(fontSize: 12, color: Color(0xff333333), fontWeight: FontWeight.bold),
  169. ),
  170. ),
  171. ],
  172. ),
  173. ),
  174. onTap: () async {
  175. //检查是否有存储权限
  176. var status = await Permission.storage.status;
  177. if (!status.isGranted) {
  178. status = await Permission.storage.request();
  179. print(status);
  180. return;
  181. }
  182. if (item.type == 'wx') {
  183. _shareByMob(ShareSDKPlatforms.wechatSession);
  184. } else if (item.type == 'pyq') {
  185. _shareByMob(ShareSDKPlatforms.wechatTimeline);
  186. } else if (item.type == 'qq') {
  187. _shareByMob(ShareSDKPlatforms.qq);
  188. } else if (item.type == 'qq_space') {
  189. _shareByMob(ShareSDKPlatforms.qZone);
  190. } else if (item.type == 'weibo') {
  191. _shareByMob(ShareSDKPlatforms.sina);
  192. } else if (item.type == 'more_setting') {
  193. _shareBySystem();
  194. }
  195. },
  196. );
  197. }
  198. // mob分享,只能单图分享,多图分享调用系统分享
  199. void _shareByMob(ShareSDKPlatform plateform) async {
  200. int count = 0;
  201. if (widget.model.poster != null) {
  202. count++;
  203. }
  204. count += (widget.model?.image?.length ?? 0);
  205. // 多图分享
  206. if (count > 1) {
  207. _shareMultipleImages();
  208. return;
  209. }
  210. Loading.show(context);
  211. SSDKMap params;
  212. if (widget.model.poster != null) {
  213. String path = await _savePoster();
  214. if (path != null && path != '') {
  215. params = SSDKMap()
  216. ..setGeneral(
  217. widget.model?.title ?? '',
  218. widget.model?.content ?? '',
  219. Platform.isIOS ? path : null,
  220. null,
  221. Platform.isAndroid ? path : null,
  222. null,
  223. null,
  224. null,
  225. null,
  226. null,
  227. SSDKContentTypes.image,
  228. );
  229. }
  230. } else {
  231. params = SSDKMap()
  232. ..setGeneral(
  233. widget.model?.title ?? '',
  234. widget.model?.content ?? '',
  235. Platform.isIOS ? widget.model.image : null,
  236. Platform.isAndroid ? widget.model.image.first : null,
  237. null,
  238. widget.model.url,
  239. null,
  240. null,
  241. null,
  242. null,
  243. SSDKContentTypes.auto,
  244. );
  245. }
  246. SharesdkPlugin.share(plateform, params, (SSDKResponseState state, Map userdata, Map contentEntity, SSDKError error) {
  247. if (state == SSDKResponseState.Fail) {
  248. Fluttertoast.showToast(msg: '分享失败');
  249. } else if (state == SSDKResponseState.Success) {
  250. Fluttertoast.showToast(msg: '分享成功');
  251. } else if (state == SSDKResponseState.Cancel) {
  252. Fluttertoast.showToast(msg: '取消分享');
  253. }
  254. Logger.debug('${state}, ${error.rawData}');
  255. Loading.dismiss();
  256. });
  257. }
  258. // 系统分享,只能分享图片或者文字,不能组合分享
  259. void _shareBySystem() async {
  260. int count = 0;
  261. if (widget.model.poster != null) {
  262. count++;
  263. }
  264. count += (widget.model?.image?.length ?? 0);
  265. // 多图分享
  266. if (count > 1) {
  267. _shareMultipleImages();
  268. return;
  269. }
  270. if (widget.model.poster != null) {
  271. String path = await _savePoster();
  272. if (path != null && path != '') {
  273. ShareExtend.share(path, 'image');
  274. }
  275. } else {
  276. ShareExtend.share(widget.model.content, 'text');
  277. }
  278. }
  279. Future<String> _savePoster() async {
  280. String path;
  281. if (widget.model.poster != null) {
  282. // 检查并请求权限
  283. var status = await Permission.storage.status;
  284. if (status != PermissionStatus.granted) {
  285. status = await Permission.storage.request();
  286. }
  287. if (status == PermissionStatus.denied) {
  288. Fluttertoast.showToast(msg: '暂无权限,分享失败');
  289. return null;
  290. }
  291. try {
  292. // 保存到本地路径
  293. final tempDir = await getTemporaryDirectory();
  294. final file = await File('${tempDir.path}/image.jpg').create();
  295. file.writeAsBytesSync(widget.model.poster);
  296. path = file.path;
  297. Logger.debug(file.path);
  298. } catch (err, s) {
  299. Logger.error(err.toString(), s.toString());
  300. Fluttertoast.showToast(msg: '分享失败');
  301. return null;
  302. }
  303. }
  304. return path;
  305. }
  306. // 多图分享,调用系统分享
  307. void _shareMultipleImages() async {
  308. List<String> paths = List();
  309. String path = await _savePoster();
  310. if (path != null && path != '') {
  311. paths.add(path);
  312. }
  313. Loading.show(context);
  314. List<String> downPaths = await ImageDownloadUtil.download(widget.model.image);
  315. paths.addAll(downPaths);
  316. ShareExtend.shareMultiple(paths, "image", subject: "");
  317. Loading.dismiss();
  318. }
  319. }