scan_dialog.dart 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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. late 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 = await Permission.camera.status;
  67. // var status = await PermissionHandler().checkPermissionStatus(PermissionGroup.camera);
  68. if (status != PermissionStatus.granted) {
  69. var future = await [Permission.camera].request();
  70. // var future = await PermissionHandler().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(bottom: 24 + MediaQuery.of(context).padding.bottom),
  85. child: IconButton(
  86. icon: Icon(snapshot.data! ? Icons.flash_on : Icons.flash_off),
  87. color: Colors.white,
  88. iconSize: 46,
  89. onPressed: () {
  90. if (snapshot.data!) {
  91. _controller.setFlashMode(false);
  92. } else {
  93. _controller.setFlashMode(true);
  94. }
  95. setState(() {});
  96. }),
  97. )
  98. : Container();
  99. }
  100. }
  101. class ScanImageView extends StatefulWidget {
  102. final Widget child;
  103. const ScanImageView({Key? key, required this.child}) : super(key: key);
  104. @override
  105. _ScanImageViewState createState() => _ScanImageViewState();
  106. }
  107. class _ScanImageViewState extends State<ScanImageView> with TickerProviderStateMixin {
  108. late AnimationController controller;
  109. @override
  110. void initState() {
  111. super.initState();
  112. controller = AnimationController(vsync: this, duration: Duration(milliseconds: 1000));
  113. controller.repeat(reverse: true);
  114. }
  115. @override
  116. void dispose() {
  117. controller.dispose();
  118. super.dispose();
  119. }
  120. @override
  121. Widget build(BuildContext context) {
  122. return AnimatedBuilder(
  123. animation: controller,
  124. builder: (BuildContext context, Widget? child) => CustomPaint(
  125. foregroundPainter: _ScanPainter(controller.value, Colors.white, Colors.green),
  126. child: widget.child,
  127. willChange: true,
  128. ));
  129. }
  130. }
  131. class _ScanPainter extends CustomPainter {
  132. final double value;
  133. final Color borderColor;
  134. final Color scanColor;
  135. _ScanPainter(this.value, this.borderColor, this.scanColor);
  136. Paint? _paint;
  137. @override
  138. void paint(Canvas canvas, Size size) {
  139. if (_paint == null) {
  140. initPaint();
  141. }
  142. double width = size.width;
  143. double height = size.height;
  144. double boxWidth = size.width * 2 / 3;
  145. double boxHeight = height / 4;
  146. double left = (width - boxWidth) / 2;
  147. double top = boxHeight;
  148. double bottom = boxHeight * 2;
  149. double right = left + boxWidth;
  150. _paint!.color = borderColor;
  151. final rect = Rect.fromLTWH(left, top, boxWidth, boxHeight);
  152. canvas.drawRect(rect, _paint!);
  153. _paint!.strokeWidth = 3;
  154. Path path1 = Path()
  155. ..moveTo(left, top + 10)
  156. ..lineTo(left, top)
  157. ..lineTo(left + 10, top);
  158. canvas.drawPath(path1, _paint!);
  159. Path path2 = Path()
  160. ..moveTo(left, bottom - 10)
  161. ..lineTo(left, bottom)
  162. ..lineTo(left + 10, bottom);
  163. canvas.drawPath(path2, _paint!);
  164. Path path3 = Path()
  165. ..moveTo(right, bottom - 10)
  166. ..lineTo(right, bottom)
  167. ..lineTo(right - 10, bottom);
  168. canvas.drawPath(path3, _paint!);
  169. Path path4 = Path()
  170. ..moveTo(right, top + 10)
  171. ..lineTo(right, top)
  172. ..lineTo(right - 10, top);
  173. canvas.drawPath(path4, _paint!);
  174. _paint!.color = scanColor;
  175. final scanRect = Rect.fromLTWH(left + 10, top + 10 + (value * (boxHeight - 20)), boxWidth - 20, 3);
  176. _paint!.shader = LinearGradient(colors: <Color>[
  177. Colors.white54,
  178. Colors.white,
  179. Colors.white54,
  180. ], stops: [
  181. 0.0,
  182. 0.5,
  183. 1,
  184. ]).createShader(scanRect);
  185. canvas.drawRect(scanRect, _paint!);
  186. }
  187. @override
  188. bool shouldRepaint(CustomPainter oldDelegate) {
  189. return true;
  190. }
  191. void initPaint() {
  192. _paint = Paint()
  193. ..style = PaintingStyle.stroke
  194. ..strokeWidth = 1
  195. ..isAntiAlias = true
  196. ..strokeCap = StrokeCap.round
  197. ..strokeJoin = StrokeJoin.round;
  198. }
  199. }