fqreader.dart 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. library fqreader;
  2. import 'dart:async';
  3. import 'dart:ui' as ui;
  4. import 'package:flutter/material.dart';
  5. import 'package:flutter/services.dart';
  6. typedef ScanEvent = Future<bool> Function(String value);
  7. class _Fqreader {
  8. static const MethodChannel _channel =
  9. const MethodChannel('fqreader');
  10. static Future<int> initView({
  11. @required Rect viewRect,
  12. @required Rect scanRect,
  13. @required List<ScanType> scanType,
  14. double devicePixelRatio
  15. }) async {
  16. var scanStr = new List<String>();
  17. scanType.forEach((item){
  18. scanStr.add(item.toString());
  19. });
  20. final int textureId = await _channel.invokeMethod('initView',{
  21. "viewRect":{
  22. "left":(viewRect.left * devicePixelRatio).toInt(),
  23. "top":(viewRect.top* devicePixelRatio).toInt(),
  24. "right":(viewRect.right* devicePixelRatio).toInt(),
  25. "bottom":(viewRect.bottom* devicePixelRatio).toInt()
  26. },
  27. "scanRect":{
  28. "left":(scanRect.left* devicePixelRatio).toInt(),
  29. "top":(scanRect.top* devicePixelRatio).toInt(),
  30. "right":(scanRect.right* devicePixelRatio).toInt(),
  31. "bottom":(scanRect.bottom* devicePixelRatio).toInt(),
  32. },
  33. "scanType": scanStr
  34. });
  35. return textureId;
  36. }
  37. static Future startScan() async{
  38. await _channel.invokeMethod('startScan');
  39. }
  40. static Future stopScan() async{
  41. await _channel.invokeMethod('stopScan');
  42. }
  43. static Future turnOn() async{
  44. await _channel.invokeMethod("turnOn");
  45. }
  46. static Future turnOff() async{
  47. await _channel.invokeMethod("turnOff");
  48. }
  49. static Future release() async{
  50. await _channel.invokeMethod("release");
  51. }
  52. }
  53. class ScanView extends StatefulWidget{
  54. /**
  55. * 扫描事件
  56. */
  57. final ScanEvent onScan;
  58. /**
  59. * 扫描区域大小
  60. */
  61. final Rect scanRect;
  62. /**
  63. * ScanView控件大小
  64. */
  65. final Rect viewRect;
  66. /**
  67. * 是否立即扫描
  68. */
  69. final bool autoScan;
  70. /**
  71. * 是否连续扫描
  72. */
  73. final bool continuityScan;
  74. /**
  75. * 连续扫描间隔
  76. */
  77. final Duration scanInterval;
  78. /**
  79. * 扫描的条码类型
  80. */
  81. final List<ScanType> scanType;
  82. const ScanView({
  83. Key key,
  84. this.onScan,
  85. @required this.viewRect,
  86. @required this.scanRect,
  87. this.scanType = const [ScanType.QR_CODE],
  88. this.autoScan = true,
  89. this.continuityScan = false,
  90. this.scanInterval = const Duration(milliseconds:500)})
  91. : super(key:key);
  92. @override
  93. State<StatefulWidget> createState() =>ScanViewState();
  94. }
  95. class ScanViewState extends State<ScanView>{
  96. int _textureId;
  97. StreamSubscription _readySubscription;
  98. @override
  99. void initState() {
  100. // TODO: implement initState
  101. super.initState();
  102. MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window);
  103. _Fqreader.initView(
  104. viewRect: widget.viewRect,
  105. scanRect:widget.scanRect,
  106. devicePixelRatio:mediaQuery.devicePixelRatio,
  107. scanType: widget.scanType
  108. ).then((textureId){
  109. setState(() {
  110. _textureId = textureId;
  111. });
  112. if(widget.autoScan){
  113. _Fqreader.startScan();
  114. }
  115. _readySubscription = new EventChannel('fqreader/scanEvents$_textureId')
  116. .receiveBroadcastStream()
  117. .listen(_listener);
  118. });
  119. }
  120. @override
  121. Widget build(BuildContext context) {
  122. return _textureId != null
  123. ? new Texture(textureId: _textureId)
  124. : new Container();
  125. }
  126. @override
  127. void dispose(){
  128. super.dispose();
  129. _readySubscription.cancel();
  130. _Fqreader.release();
  131. }
  132. /**
  133. * 开始扫描
  134. */
  135. Future startScan() async{
  136. await _Fqreader.startScan();
  137. }
  138. /**
  139. * 暂停扫描
  140. */
  141. Future stopScan() async{
  142. await _Fqreader.stopScan();
  143. }
  144. /**
  145. * 开灯
  146. */
  147. Future turnOn() async{
  148. await _Fqreader.turnOn();
  149. }
  150. /**
  151. * 关灯
  152. */
  153. Future turnOff() async{
  154. await _Fqreader.turnOff();
  155. }
  156. void _listener(dynamic value) {
  157. if(widget != null)
  158. {
  159. if(!widget.continuityScan) //是否连续扫描
  160. {
  161. _Fqreader.stopScan();
  162. }
  163. widget.onScan(value).then((result){
  164. if(widget.continuityScan && result){
  165. Future.delayed(widget.scanInterval,(){
  166. _Fqreader.startScan();
  167. });
  168. }else{
  169. _Fqreader.stopScan();
  170. }
  171. });
  172. }
  173. }
  174. }
  175. enum ScanType{
  176. /**
  177. * 普通二维码
  178. */
  179. QR_CODE,
  180. /**
  181. * 二维码 主要用于航空。比如坐飞机行李箱上贴的便签
  182. */
  183. AZTEC,
  184. /**
  185. * 条形码
  186. */
  187. CODABAR,
  188. /**
  189. * CODE 39 条形码
  190. */
  191. CODE_39,
  192. /**
  193. * CODE 92 条形码
  194. */
  195. CODE_93,
  196. /**
  197. * CODE 128 条形码
  198. */
  199. CODE_128,
  200. /**
  201. * 商品用条形码 EAN8
  202. */
  203. EAN8,
  204. /**
  205. * 商品用条形码 EAN13
  206. */
  207. EAN13,
  208. /**
  209. * 全球贸易货号。主要用于运输方面的条形码
  210. */
  211. ITF,
  212. /**
  213. * 一种二维码
  214. */
  215. DATA_MATRIX,
  216. /**
  217. * PDF417条码是一种高密度、高信息含量的便携式数据文件
  218. */
  219. PDF_417
  220. }