The QR Code Scanner package for Appeto SDK.
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

255 строки
6.1 KiB

  1. import 'dart:async';
  2. import 'package:flutter/foundation.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter/services.dart';
  5. import 'package:qr_code_scanner/qr_code_scanner.dart';
  6. typedef QRViewCreatedCallback = void Function(QRViewController);
  7. enum BarcodeFormat {
  8. /// Aztec 2D barcode format.
  9. aztec,
  10. /// CODABAR 1D format.
  11. codabar,
  12. /// Code 39 1D format.
  13. code39,
  14. /// Code 93 1D format.
  15. code93,
  16. /// Code 128 1D format.
  17. code128,
  18. /// Data Matrix 2D barcode format.
  19. dataMatrix,
  20. /// EAN-8 1D format.
  21. ean8,
  22. /// EAN-13 1D format.
  23. ean13,
  24. /// ITF (Interleaved Two of Five) 1D format.
  25. itf,
  26. /// MaxiCode 2D barcode format.
  27. maxicode,
  28. /// PDF417 format.
  29. pdf417,
  30. /// QR Code 2D barcode format.
  31. qrcode,
  32. /// RSS 14
  33. rss14,
  34. /// RSS EXPANDED
  35. rssExpanded,
  36. /// UPC-A 1D format.
  37. upcA,
  38. /// UPC-E 1D format.
  39. upcE,
  40. /// UPC/EAN extension format. Not a stand-alone format.
  41. upcEanExtension
  42. }
  43. const _formatNames = <String, BarcodeFormat>{
  44. 'AZTEC': BarcodeFormat.aztec,
  45. 'CODABAR': BarcodeFormat.codabar,
  46. 'CODE_39': BarcodeFormat.code39,
  47. 'CODE_93': BarcodeFormat.code93,
  48. 'CODE_128': BarcodeFormat.code128,
  49. 'DATA_MATRIX': BarcodeFormat.dataMatrix,
  50. 'EAN_8': BarcodeFormat.ean8,
  51. 'EAN_13': BarcodeFormat.ean13,
  52. 'ITF': BarcodeFormat.itf,
  53. 'MAXICODE': BarcodeFormat.maxicode,
  54. 'PDF_417': BarcodeFormat.pdf417,
  55. 'QR_CODE': BarcodeFormat.qrcode,
  56. 'RSS_14': BarcodeFormat.rss14,
  57. 'RSS_EXPANDED': BarcodeFormat.rssExpanded,
  58. 'UPC_A': BarcodeFormat.upcA,
  59. 'UPC_E': BarcodeFormat.upcE,
  60. 'UPC_EAN_EXTENSION': BarcodeFormat.upcEanExtension,
  61. };
  62. class Barcode {
  63. Barcode(this.code, this.format, this.rawBytes);
  64. final String code;
  65. final BarcodeFormat format;
  66. /// Raw bytes are only supported by Android.
  67. final List<int> rawBytes;
  68. }
  69. class QRView extends StatefulWidget {
  70. const QRView({
  71. @required Key key,
  72. @required this.onQRViewCreated,
  73. this.overlay,
  74. this.overlayMargin = EdgeInsets.zero,
  75. }) : assert(key != null),
  76. assert(onQRViewCreated != null),
  77. super(key: key);
  78. final QRViewCreatedCallback onQRViewCreated;
  79. final ShapeBorder overlay;
  80. final EdgeInsetsGeometry overlayMargin;
  81. @override
  82. State<StatefulWidget> createState() => _QRViewState();
  83. }
  84. class _QRViewState extends State<QRView> {
  85. @override
  86. Widget build(BuildContext context) {
  87. return Stack(
  88. children: [
  89. _getPlatformQrView(widget.key),
  90. if (widget.overlay != null)
  91. Container(
  92. padding: widget.overlayMargin,
  93. decoration: ShapeDecoration(
  94. shape: widget.overlay,
  95. ),
  96. )
  97. else
  98. Container(),
  99. ],
  100. );
  101. }
  102. Widget _getPlatformQrView(GlobalKey key) {
  103. Widget _platformQrView;
  104. switch (defaultTargetPlatform) {
  105. case TargetPlatform.android:
  106. _platformQrView = AndroidView(
  107. viewType: 'net.touchcapture.qr.flutterqr/qrview',
  108. onPlatformViewCreated: _onPlatformViewCreated,
  109. );
  110. break;
  111. case TargetPlatform.iOS:
  112. _platformQrView = UiKitView(
  113. viewType: 'net.touchcapture.qr.flutterqr/qrview',
  114. onPlatformViewCreated: _onPlatformViewCreated,
  115. creationParams:
  116. _CreationParams.fromWidget(MediaQuery.of(context).size.width, 400)
  117. .toMap(),
  118. creationParamsCodec: StandardMessageCodec(),
  119. );
  120. break;
  121. default:
  122. throw UnsupportedError(
  123. "Trying to use the default webview implementation for $defaultTargetPlatform but there isn't a default one");
  124. }
  125. return _platformQrView;
  126. }
  127. void _onPlatformViewCreated(int id) {
  128. if (widget.onQRViewCreated == null) {
  129. return;
  130. }
  131. widget.onQRViewCreated(QRViewController._(
  132. id, widget.key, (widget.overlay as QrScannerOverlayShape).cutOutSize));
  133. }
  134. }
  135. class _CreationParams {
  136. _CreationParams({this.width, this.height});
  137. static _CreationParams fromWidget(double width, double height) {
  138. return _CreationParams(
  139. width: width,
  140. height: height,
  141. );
  142. }
  143. final double width;
  144. final double height;
  145. Map<String, dynamic> toMap() {
  146. return <String, dynamic>{
  147. 'width': width,
  148. 'height': height,
  149. };
  150. }
  151. }
  152. class QRViewController {
  153. QRViewController._(int id, GlobalKey qrKey, double scanArea)
  154. : _channel = MethodChannel('net.touchcapture.qr.flutterqr/qrview_$id') {
  155. updateDimensions(qrKey, scanArea: scanArea);
  156. _channel.setMethodCallHandler(
  157. (call) async {
  158. switch (call.method) {
  159. case scanMethodCall:
  160. if (call.arguments != null) {
  161. final args = call.arguments as Map;
  162. final code = args['code'] as String;
  163. final rawType = args['type'] as String;
  164. // Raw bytes are only supported by Android.
  165. final rawBytes = args['rawBytes'] as List<int>;
  166. final format = _formatNames[rawType];
  167. if (format != null) {
  168. final barcode = Barcode(code, format, rawBytes);
  169. _scanUpdateController.sink.add(barcode);
  170. } else {
  171. throw Exception('Unexpected barcode type $rawType');
  172. }
  173. }
  174. }
  175. },
  176. );
  177. }
  178. static const scanMethodCall = 'onRecognizeQR';
  179. final MethodChannel _channel;
  180. final StreamController<Barcode> _scanUpdateController =
  181. StreamController<Barcode>();
  182. Stream<Barcode> get scannedDataStream => _scanUpdateController.stream;
  183. void flipCamera() {
  184. _channel.invokeMethod('flipCamera');
  185. }
  186. void toggleFlash() {
  187. _channel.invokeMethod('toggleFlash');
  188. }
  189. void pauseCamera() {
  190. _channel.invokeMethod('pauseCamera');
  191. }
  192. void resumeCamera() {
  193. _channel.invokeMethod('resumeCamera');
  194. }
  195. void dispose() {
  196. _scanUpdateController.close();
  197. }
  198. void updateDimensions(GlobalKey key, {double scanArea}) {
  199. if (defaultTargetPlatform == TargetPlatform.iOS) {
  200. final RenderBox renderBox = key.currentContext.findRenderObject();
  201. _channel.invokeMethod('setDimensions', {
  202. 'width': renderBox.size.width,
  203. 'height': renderBox.size.height,
  204. 'scanArea': scanArea ?? 0
  205. });
  206. }
  207. }
  208. }