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

365 行
11 KiB

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