Hibok
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

263 rader
8.0 KiB

  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'package:chat/data/UserData.dart';
  4. import 'package:chat/data/constants.dart';
  5. import 'package:chat/data/group_data_mgr.dart';
  6. import 'package:chat/generated/i18n.dart';
  7. import 'package:chat/home/qr_scanner_overlay.dart';
  8. import 'package:chat/utils/CustomUI.dart';
  9. import 'package:chat/utils/MessageMgr.dart';
  10. import 'package:chat/utils/app_navigator.dart';
  11. import 'package:flutter/material.dart';
  12. import 'package:flutter_qr_reader/flutter_qr_reader.dart';
  13. import 'package:flutter_qr_reader/qrcode_reader_view.dart';
  14. import 'package:image_picker/image_picker.dart';
  15. import 'package:oktoast/oktoast.dart';
  16. import 'package:url_launcher/url_launcher.dart';
  17. import 'join_group_confirm.dart';
  18. class QrScannerPage extends StatefulWidget {
  19. @override
  20. _QrScannerPageState createState() => _QrScannerPageState();
  21. }
  22. class _QrScannerPageState extends State<QrScannerPage>
  23. with SingleTickerProviderStateMixin {
  24. String scanImgPath;
  25. GlobalKey<QrcodeReaderViewState> qrViewKey = GlobalKey();
  26. AnimationController _animationController;
  27. Animation _animation;
  28. QrReaderViewController qrReaderViewController;
  29. @override
  30. void initState() {
  31. super.initState();
  32. _animationController = new AnimationController(
  33. duration: Duration(milliseconds: 600), vsync: this);
  34. _animation = Tween(begin: 1.0, end: 0.45).animate(_animationController)
  35. ..addListener(() {
  36. //这行如果不写,没有动画效果
  37. setState(() {});
  38. });
  39. _animationController.forward();
  40. }
  41. bool isScan = false;
  42. @override
  43. void dispose() {
  44. qrReaderViewController = null;
  45. super.dispose();
  46. }
  47. @override
  48. Widget build(BuildContext context) {
  49. final Size size = MediaQuery.of(context).size;
  50. final double scanWidth = 250;
  51. final double borderWidth = 5;
  52. final screenRect = Rect.fromLTWH(
  53. size.width / 2 - scanWidth / 2 + borderWidth,
  54. size.height / 2 -
  55. scanWidth / 2 +
  56. borderWidth -
  57. kBottomNavigationBarHeight,
  58. scanWidth - 2 * borderWidth,
  59. scanWidth - 2 * borderWidth,
  60. );
  61. return Scaffold(
  62. appBar: AppBar(
  63. leading: IconButton(
  64. iconSize: 22,
  65. icon: Icon(
  66. Icons.arrow_back_ios,
  67. color: Colors.white,
  68. ),
  69. onPressed: () {
  70. Navigator.of(context).pop();
  71. },
  72. ),
  73. backgroundColor: Colors.black,
  74. title: Text(I18n.of(context).scan,
  75. textScaleFactor: 1.0, style: TextStyle(color: Colors.white)),
  76. centerTitle: true,
  77. ),
  78. backgroundColor: Colors.black.withOpacity(_animation.value),
  79. body: ScanImageView(
  80. scanColor: Colors.blueAccent,
  81. scanRect: screenRect,
  82. child: Stack(
  83. alignment: Alignment.center,
  84. children: <Widget>[
  85. scanImgPath == null
  86. ? QrReaderView(
  87. width: size.width,
  88. height: size.height,
  89. callback: (container) {
  90. qrReaderViewController = container;
  91. Future.delayed(Duration(milliseconds: 600), () {
  92. qrReaderViewController.startCamera(onQrBack);
  93. });
  94. },
  95. )
  96. : SizedBox.expand(
  97. child: Image.file(
  98. File(scanImgPath),
  99. fit: BoxFit.contain,
  100. )),
  101. Positioned(
  102. left: 0,
  103. right: 0,
  104. bottom: 0,
  105. child: Container(
  106. color: Colors.black,
  107. padding: EdgeInsets.symmetric(vertical: 10),
  108. child: Row(
  109. mainAxisAlignment: MainAxisAlignment.spaceAround,
  110. children: <Widget>[
  111. _iconButton(
  112. IconData(0xe658,
  113. fontFamily: Constants.IconFontFamily),
  114. I18n.of(context).my_qr, () {
  115. AppNavigator.pushQrPage(context);
  116. }),
  117. _iconButton(
  118. IconData(0xe626,
  119. fontFamily: Constants.IconFontFamily),
  120. I18n.of(context).picture, () async {
  121. if (await CustomUI.showPhotoPermissionSetting(
  122. context)) {
  123. _scanImage();
  124. }
  125. })
  126. ],
  127. ),
  128. ))
  129. ],
  130. )),
  131. );
  132. }
  133. Future _scanImage() async {
  134. stopScan();
  135. print('_scanImage 开始');
  136. var image = await ImagePicker.pickImage(source: ImageSource.gallery);
  137. if (image == null) {
  138. startScan();
  139. return;
  140. }
  141. setState(() {
  142. scanImgPath = image.path;
  143. });
  144. final rest = await FlutterQrReader.imgScan(image);
  145. print('_scanImage $rest');
  146. onScan(rest);
  147. }
  148. void startScan() {
  149. isScan = false;
  150. qrReaderViewController.startCamera(onQrBack);
  151. }
  152. void stopScan() {
  153. qrReaderViewController.stopCamera();
  154. }
  155. onScan(String result) {
  156. if (result == null || result.length == 0) {
  157. return;
  158. }
  159. print('扫描 $result');
  160. stopScan();
  161. Navigator.of(context).pop();
  162. if (result.startsWith('https://henho.jphgames.com/')) {
  163. result = result.replaceFirst('https://henho.jphgames.com/?', '');
  164. result = utf8.decode(base64Decode(result));
  165. result = 'https://henho.jphgames.com/?' + result;
  166. var url = Uri.parse(result);
  167. var type = int.parse(url.queryParameters['type']);
  168. int expirationTime = int.parse(url.queryParameters['expirationTime']);
  169. int curTime = DateTime.now().millisecondsSinceEpoch;
  170. print('过期时间$expirationTime');
  171. if (curTime > expirationTime) {
  172. showToast(I18n.of(context).qr_outtime);
  173. return;
  174. }
  175. if (type == 1) {
  176. var targetId = int.parse(url.queryParameters['sessionId']);
  177. //群二维码
  178. print('群二维码');
  179. GroupInfoMgr().getGroupInfo(targetId, isSave: false).then((groupInfo) {
  180. print('--------------------');
  181. print(groupInfo);
  182. if (groupInfo == null) {
  183. showToast(I18n.of(context).no_goupr_info);
  184. return;
  185. }
  186. Navigator.push(Constants.getCurrentContext(),
  187. MaterialPageRoute<void>(builder: (BuildContext context) {
  188. return JoinGroupConfirmPage(
  189. groupInfoModel: groupInfo,
  190. );
  191. }));
  192. });
  193. } else {
  194. //个人二维码
  195. print('个人二维码');
  196. var targetId = int.parse(url.queryParameters['sessionId']);
  197. if (targetId == UserData().basicInfo.userId) {
  198. //我的页面
  199. MessageMgr().emit('Show My Profile');
  200. } else {
  201. AppNavigator.pushProfileInfoPage(context, targetId, addMode: 1);
  202. }
  203. }
  204. } else {
  205. //其他的条码
  206. launch(result);
  207. }
  208. }
  209. onQrBack(String result, List<Offset> points) {
  210. print('扫描结果 $result');
  211. if (isScan == true) return;
  212. isScan = true;
  213. stopScan();
  214. onScan(result);
  215. }
  216. Widget _iconButton(IconData code, String iconName, Function onTap) {
  217. return InkWell(
  218. onTap: onTap,
  219. child: Container(
  220. child: Column(children: <Widget>[
  221. Icon(
  222. code,
  223. size: 30,
  224. color: Colors.white,
  225. ),
  226. SizedBox(height: 5),
  227. Text(
  228. iconName,
  229. textScaleFactor: 1.0,
  230. style: TextStyle(color: Colors.white),
  231. )
  232. ])));
  233. }
  234. }