import 'dart:ui'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:image_gallery_saver/image_gallery_saver.dart'; import 'package:provider/provider.dart'; import 'package:sport/bean/post.dart'; import 'package:sport/pages/social/post_page.dart'; import 'package:sport/pages/social/post_share_page.dart'; import 'package:sport/provider/user_model.dart'; import 'package:sport/router/navigator_util.dart'; import 'package:sport/services/api/inject_api.dart'; import 'package:sport/utils/toast.dart'; import 'package:path_provider/path_provider.dart'; import 'package:sport/sharesdk/tencent.dart'; import 'package:sport/sharesdk/wechat.dart'; import 'package:sport/widgets/space.dart'; import 'dart:io'; import 'dart:typed_data'; import 'package:wechat_kit/wechat_kit.dart'; class MenuShareBottomContent extends StatefulWidget { final String url; // 复制的那个链接 final bool hasDownload; // 有些又download 有些没download final GlobalKey poster; // 下载海报... final String shareType; // 什么类型 Img social Link final Post post; // social 连带的 post final String hash; // 分享 link 连带的hash MenuShareBottomContent( this.shareType, { this.post, this.url = "", this.hasDownload = false, this.poster, this.hash, }); @override State createState() { // TODO: implement createState return _MenuShareBottomContentState(); } } // shareType : Img / Link / Social class _MenuShareBottomContentState extends State with TencentMixin, WechatMixin, InjectApi { List> map; Uint8List postInstance; @override listenShareMsg(WechatSdkResp resp) { Navigator.pop(context); ToastUtil.show("分享成功"); } @override void initState() { // TODO: implement initState super.initState(); map = [ { "value": "微信", "url": "share_icon_wechat", "callBack": () async { if (widget.shareType == "Img") { String path = await initFile(); wechatShareImage(path, "chat"); } else if (widget.shareType == "Link") { wechatShareLink(widget.url + "?h=${widget.hash}", "chat", Provider.of(context, listen: false).user.name); } } }, { "value": "朋友圈", "url": "share_icon_wechatmonents", "callBack": () async { if (widget.shareType == "Img") { String path = await initFile(); wechatShareImage(path, "friend"); } else if (widget.shareType == "Link") { wechatShareLink(widget.url + "?h=${widget.hash}", "friend", Provider.of(context, listen: false).user.name); } } }, { "value": "QQ", "url": "share_icon_qq", "callBack": () async { if (widget.shareType == "Img") { String path = await initFile(); qqShare(path); } else if (widget.shareType == "Link") { qqShareLink(widget.url); } } }, { "value": "社区", "url": "share_icon_community", "callBack": () async { if (widget.shareType == "social") { await NavigatorUtil.goPage( context, (contxt) => PostPage( "", post: widget.post, )); } else if (widget.shareType == "Link") { await NavigatorUtil.goPage( context, (contxt) => PostPage( "", post: widget.post, url: "http://shoes-web.hiyd.com/share", hash: widget.hash, )); } else if (widget.shareType == "Img") { String path = await initFile(); print("$path---------------------------------"); Future.delayed(new Duration(milliseconds: 200)); await NavigatorUtil.goPage( context, (context) => PostPage("",image: path)); } Navigator.pop(context, true); } }, { "value": "社区好友", "url": "share_icon_friends", "callBack": () async { if (widget.shareType == "social") { await NavigatorUtil.goPage( context, (context) => PostShareFriendsPage( post: widget.post, )); } else if (widget.shareType == "Link") { // 这里可能得组装一手 link 的 数据 ... await NavigatorUtil.goPage( context, (context) => PostShareFriendsPage(hash: widget.hash)); } else if (widget.shareType == "Img") { String path = await initFile(); String url = (await api.postChatUpload(File(path))).data["url"]; await NavigatorUtil.goPage( context, (context) => PostShareFriendsPage( image: url, )); } Navigator.pop(context, true); } }, { "value": "复制链接", "url": "share_icon_link", "callBack": () { Clipboard.setData(ClipboardData(text: widget.url)); ToastUtil.show("复制成功"); } }, { "value": "下载图片", "url": "share_icon_download", "callBack": () { _capture().then((file) async {}).whenComplete(() { print("Complete-------------------------------------------------"); }); } }, ]; if (widget.hasDownload == null || !widget.hasDownload) { map.removeLast(); } if (widget.url == null) { map.removeAt(5); } // 社区暂时先把前面的隐藏掉 if (widget.shareType == "social") { map = map.sublist(map.length - 2, map.length); } } // 封装成灵活的更通用一点... Future initFile() async { Uint8List pngBytes = await initFileUint8List(); print("$pngBytes------------------------------"); String sTempDir = (await getTemporaryDirectory()).path; bool isDirExist = await Directory(sTempDir).exists(); if (!isDirExist) { Directory(sTempDir).create(); } // QQ分享需要一个确实存在的图片 File file = await File(sTempDir + "/poster-temp-${DateTime.now().millisecondsSinceEpoch}.png") .writeAsBytes(pngBytes); print( "[file]:${file.readAsBytesSync().length}---------------${pngBytes.length}----------------"); return file.path; } Future initFileUint8List() async { try { RenderRepaintBoundary boundary = widget.poster.currentContext.findRenderObject(); //boundary.toImage()转化为ui.Image对象,不会自动为包裹的组件添加背景,不设置可能会缺失背景 var image = await boundary.toImage(pixelRatio: window.devicePixelRatio); //将image转化为byteData ByteData byteData = await image.toByteData(format: ImageByteFormat.png); //这个对象就是图片数据 Uint8List pngBytes = byteData.buffer.asUint8List(); print("成功生成图片 ----------------------------------------"); return pngBytes; } catch (e) { print(e); } return null; } Future _capture() async { Uint8List pngBytes = await initFileUint8List(); final result = await ImageGallerySaver.saveImage(pngBytes); //这个是核心的保存图片的插件 print(result); ToastUtil.show("下载成功"); } @override Widget build(BuildContext context) { // TODO: implement build return SizedBox( child: Container( margin: EdgeInsets.fromLTRB(24, 23, 24, 17), child: Column( children: [ Row( children: [ Expanded( child: Divider( endIndent: 12.0, ), ), Text( "分享至", style: Theme.of(context).textTheme.bodyText2, ), Expanded( child: Divider( indent: 12.0, ), ) ], ), SizedBox( height: 12.0, ), Expanded( child: GridView( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 4, crossAxisSpacing: 12.0, mainAxisSpacing: 18.0), children: map .map( (e) => InkWell( child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Image.asset( "lib/assets/img/${e["url"]}.png", width: 44.0, height: 44.0, ), Space( height: 6.0, ), Text( "${e["value"]}", style: Theme.of(context).textTheme.subtitle2, ), // Space(height: 8.0,), ], ), onTap: () { e["callBack"](); }, ), ) .toList()), ) ], ), ), height: 232.0, ); } } Future menuShareBottom(BuildContext context, String shareType, {Post post, String url, bool hasDownload, GlobalKey poster, String hash}) { return showModalBottomSheet( context: context, builder: (context) { return MenuShareBottomContent(shareType, post: post, url: url, hasDownload: hasDownload, poster: poster, hash: hash); }, backgroundColor: Colors.white, elevation: 10, shape: RoundedRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular(10), topRight: Radius.circular(10)), ), ); }