scan_dialog.dart 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. import 'package:flutter/material.dart';
  2. import 'package:permission_handler/permission_handler.dart';
  3. import 'package:r_scan/r_scan.dart';
  4. class RScanDialog extends StatefulWidget {
  5. @override
  6. _RScanDialogState createState() => _RScanDialogState();
  7. }
  8. class _RScanDialogState extends State<RScanDialog> {
  9. RScanController _controller;
  10. @override
  11. void initState() {
  12. super.initState();
  13. initController();
  14. }
  15. bool isFirst = true;
  16. Future<void> initController() async {
  17. _controller = RScanController();
  18. _controller.addListener(() {
  19. final result = _controller.result;
  20. if (result != null) {
  21. if (isFirst) {
  22. Navigator.of(context).pop(result);
  23. isFirst = false;
  24. }
  25. }
  26. });
  27. }
  28. @override
  29. Widget build(BuildContext context) {
  30. return Scaffold(
  31. backgroundColor: Colors.black,
  32. body: FutureBuilder<bool>(
  33. future: canOpenCameraView(),
  34. builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
  35. if (snapshot.hasData && snapshot.data == true) {
  36. return Stack(
  37. children: <Widget>[
  38. ScanImageView(
  39. child: RScanView(
  40. controller: _controller,
  41. ),
  42. ),
  43. Align(
  44. alignment: Alignment.bottomCenter,
  45. child: FutureBuilder(
  46. future: getFlashMode(),
  47. builder: _buildFlashBtn,
  48. ))
  49. ],
  50. );
  51. } else {
  52. return Container();
  53. }
  54. },
  55. ),
  56. );
  57. }
  58. Future<bool> getFlashMode() async {
  59. bool isOpen = false;
  60. try {
  61. isOpen = await _controller.getFlashMode();
  62. } catch (_) {}
  63. return isOpen;
  64. }
  65. Future<bool> canOpenCameraView() async {
  66. var status =
  67. await PermissionHandler().checkPermissionStatus(PermissionGroup.camera);
  68. if (status != PermissionStatus.granted) {
  69. var future = await PermissionHandler()
  70. .requestPermissions([PermissionGroup.camera]);
  71. for (final item in future.entries) {
  72. if (item.value != PermissionStatus.granted) {
  73. return false;
  74. }
  75. }
  76. } else {
  77. return true;
  78. }
  79. return true;
  80. }
  81. Widget _buildFlashBtn(BuildContext context, AsyncSnapshot<bool> snapshot) {
  82. return snapshot.hasData
  83. ? Padding(
  84. padding: EdgeInsets.only(
  85. bottom: 24 + MediaQuery.of(context).padding.bottom),
  86. child: IconButton(
  87. icon: Icon(snapshot.data ? Icons.flash_on : Icons.flash_off),
  88. color: Colors.white,
  89. iconSize: 46,
  90. onPressed: () {
  91. if (snapshot.data) {
  92. _controller.setFlashMode(false);
  93. } else {
  94. _controller.setFlashMode(true);
  95. }
  96. setState(() {});
  97. }),
  98. )
  99. : Container();
  100. }
  101. }
  102. class ScanImageView extends StatefulWidget {
  103. final Widget child;
  104. const ScanImageView({Key key, this.child}) : super(key: key);
  105. @override
  106. _ScanImageViewState createState() => _ScanImageViewState();
  107. }
  108. class _ScanImageViewState extends State<ScanImageView>
  109. with TickerProviderStateMixin {
  110. AnimationController controller;
  111. @override
  112. void initState() {
  113. super.initState();
  114. controller = AnimationController(
  115. vsync: this, duration: Duration(milliseconds: 1000));
  116. controller.repeat(reverse: true);
  117. }
  118. @override
  119. void dispose() {
  120. controller.dispose();
  121. super.dispose();
  122. }
  123. @override
  124. Widget build(BuildContext context) {
  125. return AnimatedBuilder(
  126. animation: controller,
  127. builder: (BuildContext context, Widget child) => CustomPaint(
  128. foregroundPainter:
  129. _ScanPainter(controller.value, Colors.white, Colors.green),
  130. child: widget.child,
  131. willChange: true,
  132. ));
  133. }
  134. }
  135. class _ScanPainter extends CustomPainter {
  136. final double value;
  137. final Color borderColor;
  138. final Color scanColor;
  139. _ScanPainter(this.value, this.borderColor, this.scanColor);
  140. Paint _paint;
  141. @override
  142. void paint(Canvas canvas, Size size) {
  143. if (_paint == null) {
  144. initPaint();
  145. }
  146. double width = size.width;
  147. double height = size.height;
  148. double boxWidth = size.width * 2 / 3;
  149. double boxHeight = height / 4;
  150. double left = (width - boxWidth) / 2;
  151. double top = boxHeight;
  152. double bottom = boxHeight * 2;
  153. double right = left + boxWidth;
  154. _paint.color = borderColor;
  155. final rect = Rect.fromLTWH(left, top, boxWidth, boxHeight);
  156. canvas.drawRect(rect, _paint);
  157. _paint.strokeWidth = 3;
  158. Path path1 = Path()
  159. ..moveTo(left, top + 10)
  160. ..lineTo(left, top)
  161. ..lineTo(left + 10, top);
  162. canvas.drawPath(path1, _paint);
  163. Path path2 = Path()
  164. ..moveTo(left, bottom - 10)
  165. ..lineTo(left, bottom)
  166. ..lineTo(left + 10, bottom);
  167. canvas.drawPath(path2, _paint);
  168. Path path3 = Path()
  169. ..moveTo(right, bottom - 10)
  170. ..lineTo(right, bottom)
  171. ..lineTo(right - 10, bottom);
  172. canvas.drawPath(path3, _paint);
  173. Path path4 = Path()
  174. ..moveTo(right, top + 10)
  175. ..lineTo(right, top)
  176. ..lineTo(right - 10, top);
  177. canvas.drawPath(path4, _paint);
  178. _paint.color = scanColor;
  179. final scanRect = Rect.fromLTWH(
  180. left + 10, top + 10 + (value * (boxHeight - 20)), boxWidth - 20, 3);
  181. _paint.shader = LinearGradient(colors: <Color>[
  182. Colors.white54,
  183. Colors.white,
  184. Colors.white54,
  185. ], stops: [
  186. 0.0,
  187. 0.5,
  188. 1,
  189. ]).createShader(scanRect);
  190. canvas.drawRect(scanRect, _paint);
  191. }
  192. @override
  193. bool shouldRepaint(CustomPainter oldDelegate) {
  194. return true;
  195. }
  196. void initPaint() {
  197. _paint = Paint()
  198. ..style = PaintingStyle.stroke
  199. ..strokeWidth = 1
  200. ..isAntiAlias = true
  201. ..strokeCap = StrokeCap.round
  202. ..strokeJoin = StrokeJoin.round;
  203. }
  204. }