Hibok
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

368 wiersze
13 KiB

  1. import 'dart:async';
  2. import 'dart:io';
  3. import 'dart:typed_data';
  4. import 'dart:ui';
  5. import 'package:cached_network_image/cached_network_image.dart';
  6. import 'package:chat/data/group_data_mgr.dart';
  7. import 'package:chat/models/group_info_model.dart';
  8. import 'package:chat/utils/screen.dart';
  9. import 'package:flutter/material.dart';
  10. import 'package:flutter/rendering.dart';
  11. import 'package:flutter/widgets.dart';
  12. //import 'package:flutter_image_compress/flutter_image_compress.dart';
  13. import 'package:flutter_native_image/flutter_native_image.dart';
  14. import '../r.dart';
  15. import 'file_cache_mgr.dart';
  16. import 'group_member_model.dart';
  17. const ImgSizeLimit = 60 * 1024;
  18. /// Widget Util.
  19. class WidgetUtil {
  20. bool _hasMeasured = false;
  21. double _width;
  22. double _height;
  23. /// Widget rendering listener.
  24. /// Widget渲染监听.
  25. /// context: Widget context.
  26. /// isOnce: true,Continuous monitoring false,Listen only once.
  27. /// onCallBack: Widget Rect CallBack.
  28. void asyncPrepare(
  29. BuildContext context, bool isOnce, ValueChanged<Rect> onCallBack) {
  30. if (_hasMeasured) return;
  31. WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) {
  32. RenderBox box = context.findRenderObject();
  33. if (box != null && box.semanticBounds != null) {
  34. if (isOnce) _hasMeasured = true;
  35. double width = box.semanticBounds.width;
  36. double height = box.semanticBounds.height;
  37. if (_width != width || _height != height) {
  38. _width = width;
  39. _height = height;
  40. if (onCallBack != null) onCallBack(box.semanticBounds);
  41. }
  42. }
  43. });
  44. }
  45. /// Widget渲染监听.
  46. void asyncPrepares(bool isOnce, ValueChanged<Rect> onCallBack) {
  47. if (_hasMeasured) return;
  48. WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) {
  49. if (isOnce) _hasMeasured = true;
  50. if (onCallBack != null) onCallBack(null);
  51. });
  52. }
  53. ///get Widget Bounds (width, height, left, top, right, bottom and so on).Widgets must be rendered completely.
  54. ///获取widget Rect
  55. static Rect getWidgetBounds(BuildContext context) {
  56. RenderBox box = context.findRenderObject();
  57. return (box != null && box.semanticBounds != null)
  58. ? box.semanticBounds
  59. : Rect.zero;
  60. }
  61. static getCompressImg(String imgPath) async {
  62. File compressedFile = await FlutterNativeImage.compressImage(imgPath,
  63. quality: 20, percentage: 25);
  64. var k =compressedFile.readAsBytesSync().toList();
  65. print('A图片压缩完毕 : ${k.length}');
  66. // compressedFile.
  67. // var compressImg = await FlutterImageCompress.compressWithFile(imgPath,
  68. // quality: 20, minWidth: Screen.width.toInt());
  69. // print('B图片压缩完毕 : ${compressImg.length}');
  70. // if (compressImg.length > ImgSizeLimit) {
  71. // //仍大于,再压缩一次
  72. // compressImg = await FlutterImageCompress.compressWithFile(imgPath,
  73. // quality: 20, minWidth: (Screen.width * 0.5).toInt());
  74. // }
  75. return k;
  76. }
  77. ///Get the coordinates of the widget on the screen.Widgets must be rendered completely.
  78. ///获取widget在屏幕上的坐标,widget必须渲染完成
  79. static Offset getWidgetLocalToGlobal(BuildContext context) {
  80. RenderBox box = context.findRenderObject();
  81. return box == null ? Offset.zero : box.localToGlobal(Offset.zero);
  82. }
  83. /// get image width height,load error return Rect.zero.(unit px)
  84. /// 获取图片宽高,加载错误情况返回 Rect.zero.(单位 px)
  85. /// image
  86. /// url network
  87. /// local url , package
  88. static Future<Rect> getImageWH(
  89. {Image image, String url, String localUrl, String package}) {
  90. if (image == null && url == null && localUrl == null) {
  91. return Future.value(Rect.zero);
  92. }
  93. Completer<Rect> completer = Completer<Rect>();
  94. Image img = image != null
  95. ? image
  96. : ((url != null && url.isNotEmpty)
  97. ? Image.network(url)
  98. : Image.asset(localUrl, package: package));
  99. img.image
  100. .resolve(new ImageConfiguration())
  101. .addListener(new ImageStreamListener(
  102. (ImageInfo info, bool _) {
  103. completer.complete(Rect.fromLTWH(0, 0, info.image.width.toDouble(),
  104. info.image.height.toDouble()));
  105. },
  106. onError: (dynamic exception, StackTrace stackTrace) {
  107. completer.completeError(exception, stackTrace);
  108. },
  109. ));
  110. return completer.future;
  111. }
  112. /// get image width height, load error throw exception.(unit px)
  113. /// 获取图片宽高,加载错误会抛出异常.(单位 px)
  114. /// image
  115. /// url network
  116. /// local url (full path/全路径,example:"assets/images/ali_connors.png",""assets/images/3.0x/ali_connors.png"" );
  117. /// package
  118. static Future<Rect> getImageWHE(
  119. {Image image, String url, String localUrl, String package}) {
  120. if (image == null && url == null && localUrl == null) {
  121. return Future.value(Rect.zero);
  122. }
  123. Completer<Rect> completer = Completer<Rect>();
  124. Image img = image != null
  125. ? image
  126. : ((url != null && url.isNotEmpty)
  127. ? Image.network(url)
  128. : Image.asset(localUrl, package: package));
  129. img.image
  130. .resolve(new ImageConfiguration())
  131. .addListener(new ImageStreamListener(
  132. (ImageInfo info, bool _) {
  133. completer.complete(Rect.fromLTWH(0, 0, info.image.width.toDouble(),
  134. info.image.height.toDouble()));
  135. },
  136. onError: (dynamic exception, StackTrace stackTrace) {
  137. completer.completeError(exception, stackTrace);
  138. },
  139. ));
  140. return completer.future;
  141. }
  142. static ImageProvider groupAvatar(String path ) {
  143. path = FileCacheMgr.replacePath(path);
  144. Uint8List fileData = File(path).readAsBytesSync();
  145. // print('fileData ${fileData.length}');
  146. return MemoryImage(fileData);
  147. }
  148. static Widget getAvatarNew(GroupInfoModel model,GlobalKey key,Function backPath) {
  149. List<GroupMemberModel> members =[];
  150. for(int k=0;k< model.members.length;k++){ //只加入存在群的
  151. GroupMemberModel mo = model.members[k];
  152. if(mo.inGroup==1){
  153. members.add(mo);
  154. }
  155. }
  156. if(model.image!=null && model.image.length>2){
  157. print('${model.name} 群头像地址:${model.image}');
  158. File file = new File(model.image);
  159. // int filelength = file.readAsBytesSync().length;
  160. // print('群头像地址file size : $filelength');
  161. if( file.existsSync()){ //防止头像文件被清除后
  162. Uint8List pngBytes =file.readAsBytesSync();
  163. print('pngBytes.lengthInBytes length;${pngBytes.lengthInBytes}');
  164. if(pngBytes.lengthInBytes>8000){
  165. return ClipRRect( borderRadius: BorderRadius.circular(5),child:Container(color: Color(0xffE9E9E9),width: 52,height: 52,child:
  166. Image.file(
  167. File(FileCacheMgr.replacePath(model.image)),
  168. fit: BoxFit.contain,
  169. width: 50,
  170. height: 50,
  171. ),) ,);
  172. }
  173. }else{
  174. backPath('');
  175. }
  176. }
  177. ///先让下面的图片显示,5秒后截图保存图片
  178. Future.delayed(Duration(seconds: 3),() async{
  179. // print('没有群图片-开始生成保存到本地:${model.members.length}');
  180. try {
  181. RenderRepaintBoundary boundary =
  182. key.currentContext.findRenderObject();
  183. var image = await boundary.toImage(pixelRatio:2);
  184. ByteData byteData = await image.toByteData(format: ImageByteFormat.png);
  185. Uint8List pngBytes = byteData.buffer.asUint8List();
  186. File file =await FileCacheMgr().writeFile(model.sessionId.toString(),pngBytes);
  187. print('图片地址byteData${byteData.lengthInBytes}');
  188. if(byteData.lengthInBytes>8000 && members.length>1){ //图片保存成功
  189. GroupInfoMgr().updateAvatar(model.sessionId,file.path);
  190. backPath(file.path);
  191. }
  192. // ImageGallerySaver.saveImage(pngBytes);
  193. // return pngBytes;//这个对象就是图片数据
  194. } catch (e) {
  195. print(e);
  196. }
  197. });
  198. if(members.length>9){
  199. members = members.sublist(0,9);
  200. }
  201. if (members.length > 0) {
  202. double itemSize = 10;
  203. switch (members.length) {
  204. case 1:
  205. return RepaintBoundary(key: key,child: ClipRRect(borderRadius: BorderRadius.circular(3),child: Container(color: Color(0xffE9E9E9),width: 52,height: 52,child: Padding(padding: EdgeInsets.all(1),child: CachedNetworkImage(
  206. imageUrl: members[0].avtar,
  207. width: 45,
  208. height: 45,
  209. placeholder: (context, url) =>
  210. Image.asset(R.assetsImagesDefaultNorAvatar,width: 45,
  211. height: 45,)
  212. ),),),),);
  213. break;
  214. case 2:
  215. return RepaintBoundary(key: key,child: ClipRRect(borderRadius: BorderRadius.circular(3),child: Container(color: Color(0xffE9E9E9),width: 52,height: 52,child: Row(children: <Widget>[
  216. Padding(padding: EdgeInsets.all(1),child: ClipRRect(
  217. borderRadius: BorderRadius.circular(3),
  218. child: CachedNetworkImage(
  219. imageUrl: members[0].avtar,
  220. width: 23,
  221. height: 23,
  222. placeholder: (context, url) =>
  223. Image.asset(R.assetsImagesDefaultNorAvatar, width: 23,
  224. height: 23,)
  225. ),
  226. ),),
  227. Padding(padding: EdgeInsets.all(1),child: ClipRRect(
  228. borderRadius: BorderRadius.circular(3),
  229. child: CachedNetworkImage(
  230. imageUrl: members[1].avtar,
  231. width: 23,
  232. height: 23,placeholder: (context, url) =>
  233. Image.asset(R.assetsImagesDefaultNorAvatar,width: 23,
  234. height: 23,)
  235. ),
  236. ),)
  237. ],),),),);
  238. case 3:
  239. return RepaintBoundary(key: key,child: ClipRRect(borderRadius: BorderRadius.circular(3),child: Container(color: Color(0xffE9E9E9),width: 52,height: 52,child: Column(children: <Widget>[
  240. Padding(padding: EdgeInsets.all(1),child: ClipRRect(
  241. borderRadius: BorderRadius.circular(3),
  242. child: CachedNetworkImage(
  243. imageUrl: members[0].avtar,
  244. width: 23,
  245. height: 23,placeholder: (context, url) =>
  246. Image.asset(R.assetsImagesDefaultNorAvatar,width: 23,
  247. height: 23,)
  248. ),
  249. ),),
  250. Row(children: <Widget>[
  251. Padding(padding: EdgeInsets.all(1),child: ClipRRect(
  252. borderRadius: BorderRadius.circular(3),
  253. child: CachedNetworkImage(
  254. imageUrl: members[1].avtar,
  255. width: 23,
  256. height: 23,placeholder: (context, url) =>
  257. Image.asset(R.assetsImagesDefaultNorAvatar,width: 23,
  258. height: 23,)
  259. ),
  260. ),),
  261. Padding(padding: EdgeInsets.all(1),child: ClipRRect(
  262. borderRadius: BorderRadius.circular(3),
  263. child: CachedNetworkImage(
  264. imageUrl: members[2].avtar,
  265. width: 23,
  266. height: 23,placeholder: (context, url) =>
  267. Image.asset(R.assetsImagesDefaultNorAvatar,width: 23,
  268. height: 23,)
  269. ),
  270. ),)
  271. ],)
  272. ],),),),);
  273. }
  274. if (members.length == 4) {
  275. itemSize = 23;
  276. } else {
  277. itemSize = 15;
  278. }
  279. List<Widget> widgetList = [];
  280. for (int k = 0; k < members.length; k++) {
  281. widgetList.add(Padding(padding: EdgeInsets.all(1),child: ClipRRect(
  282. borderRadius: BorderRadius.circular(3),
  283. child: CachedNetworkImage(
  284. imageUrl: members[k].avtar,
  285. width: itemSize,
  286. height: itemSize,placeholder: (context, url) =>
  287. Image.asset(R.assetsImagesDefaultNorAvatar,width: itemSize,
  288. height: itemSize,)
  289. ),
  290. ),));
  291. }
  292. return RepaintBoundary(key: key,child: ClipRRect(borderRadius: BorderRadius.circular(3),child: Container(
  293. color: Color(0xffE9E9E9),
  294. width: 52,
  295. height: 52,
  296. alignment: Alignment.center,
  297. child: Wrap(
  298. crossAxisAlignment: WrapCrossAlignment.start, children: widgetList),
  299. ),),);
  300. } else {
  301. return ClipRRect(borderRadius: BorderRadius.circular(3),child: Container(color: Color(0xffE9E9E9),),);
  302. }
  303. }
  304. }