Advertisement
rifki_cs29

CameraOverlay

Mar 9th, 2023
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.79 KB | None | 0 0
  1. import 'package:camera/camera.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/services.dart';
  4. import 'package:module_core/widgets/camera_overlay/overlay_shape.dart';
  5.  
  6. typedef XFileCallback = void Function(XFile file);
  7.  
  8. class CameraOverlay extends StatefulWidget {
  9. const CameraOverlay({
  10. required this.camera,
  11. required this.onCapture,
  12. Key? key,
  13. this.flash = false,
  14. this.enableCaptureButton = true,
  15. this.label,
  16. this.info,
  17. this.loadingWidget,
  18. this.infoMargin,
  19. }) : super(key: key);
  20. final CameraDescription camera;
  21. final bool flash;
  22. final bool enableCaptureButton;
  23. final XFileCallback onCapture;
  24. final String? label;
  25. final String? info;
  26. final Widget? loadingWidget;
  27. final EdgeInsets? infoMargin;
  28.  
  29. @override
  30. State<CameraOverlay> createState() => _FlutterCameraOverlayState();
  31. }
  32.  
  33. class _FlutterCameraOverlayState extends State<CameraOverlay>
  34. with WidgetsBindingObserver {
  35. _FlutterCameraOverlayState();
  36.  
  37. late CameraController controller;
  38.  
  39. @override
  40. void initState() {
  41. super.initState();
  42. WidgetsBinding.instance.addObserver(this);
  43.  
  44. controller = CameraController(
  45. widget.camera,
  46. ResolutionPreset.high,
  47. );
  48. controller.initialize().then((_) {
  49. if (!mounted) {
  50. return;
  51. }
  52. setState(() {});
  53. }).catchError((Object e) {
  54. if (e is CameraException) {
  55. switch (e.code) {
  56. case 'CameraAccessDenied':
  57. break;
  58. case 'CameraAccessDeniedWithoutPrompt':
  59. // iOS only
  60. break;
  61. case 'CameraAccessRestricted':
  62. // iOS only
  63. break;
  64. case 'AudioAccessDenied':
  65. break;
  66. case 'AudioAccessDeniedWithoutPrompt':
  67. // iOS only
  68. break;
  69. case 'AudioAccessRestricted':
  70. // iOS only
  71. break;
  72. default:
  73. // _showCameraException(e);
  74. break;
  75. }
  76. }
  77. });
  78. }
  79.  
  80. @override
  81. void didUpdateWidget(oldWidget) {
  82. super.didUpdateWidget(oldWidget);
  83. controller.dispose();
  84. }
  85.  
  86. @override
  87. void dispose() {
  88. controller.dispose();
  89. WidgetsBinding.instance.removeObserver(this);
  90. super.dispose();
  91. }
  92.  
  93. @override
  94. void didChangeAppLifecycleState(AppLifecycleState state) {
  95. if (!controller.value.isInitialized) {
  96. return;
  97. }
  98.  
  99. if (state == AppLifecycleState.inactive) {
  100. controller.dispose();
  101. } else if (state == AppLifecycleState.resumed) {
  102. onNewCameraSelected(controller.description);
  103. }
  104. }
  105.  
  106. Future<void> onNewCameraSelected(CameraDescription cameraDescription) async {
  107. // await controller.dispose();
  108.  
  109. controller = CameraController(
  110. cameraDescription,
  111. ResolutionPreset.high,
  112. );
  113.  
  114. controller.addListener(() {
  115. if (mounted) {
  116. setState(() {});
  117. }
  118. if (controller.value.hasError) {
  119. //if error
  120. }
  121. });
  122.  
  123. try {
  124. await controller.initialize();
  125. } on CameraException catch (e) {
  126. switch (e.code) {
  127. case 'CameraAccessDenied':
  128. break;
  129. case 'CameraAccessDeniedWithoutPrompt':
  130. // iOS only
  131. break;
  132. case 'CameraAccessRestricted':
  133. // iOS only
  134. break;
  135. case 'AudioAccessDenied':
  136. break;
  137. case 'AudioAccessDeniedWithoutPrompt':
  138. // iOS only
  139. break;
  140. case 'AudioAccessRestricted':
  141. // iOS only
  142. break;
  143. default:
  144. // _showCameraException(e);
  145. break;
  146. }
  147. }
  148.  
  149. if (mounted) {
  150. setState(() {});
  151. }
  152. }
  153.  
  154. @override
  155. Widget build(BuildContext context) {
  156. Widget loadingWidget = widget.loadingWidget ??
  157. const Center(
  158. child: CircularProgressIndicator(
  159. color: Colors.orangeAccent,
  160. ),
  161. );
  162.  
  163. if (!controller.value.isInitialized) {
  164. return loadingWidget;
  165. }
  166.  
  167. controller
  168. .setFlashMode(widget.flash == true ? FlashMode.auto : FlashMode.off);
  169.  
  170. // to normal camera stretched
  171. var camera = controller.value;
  172. final size = MediaQuery.of(context).size;
  173. var scale = size.aspectRatio * camera.aspectRatio;
  174. if (scale < 1) scale = 1 / scale;
  175.  
  176. return Stack(
  177. alignment: Alignment.bottomCenter,
  178. fit: StackFit.expand,
  179. children: [
  180. Transform.scale(
  181. scale: scale,
  182. child: Center(
  183. child: CameraPreview(controller),
  184. ),
  185. ),
  186. const OverlayShape(),
  187. if (widget.label != null || widget.info != null)
  188. Align(
  189. alignment: Alignment.topCenter,
  190. child: Container(
  191. margin: widget.infoMargin ??
  192. const EdgeInsets.only(top: 100, left: 20, right: 20),
  193. child: Column(
  194. children: [
  195. if (widget.label != null)
  196. Text(
  197. widget.label ?? 'label',
  198. style: const TextStyle(
  199. color: Colors.white,
  200. fontSize: 24,
  201. fontWeight: FontWeight.w700,
  202. ),
  203. ),
  204. if (widget.info != null)
  205. Flexible(
  206. child: Text(
  207. widget.info ?? 'info',
  208. textAlign: TextAlign.center,
  209. style: const TextStyle(
  210. color: Colors.white,
  211. fontSize: 16,
  212. fontWeight: FontWeight.w500,
  213. ),
  214. ),
  215. ),
  216. ],
  217. ),
  218. ),
  219. ),
  220. if (widget.enableCaptureButton)
  221. Align(
  222. alignment: Alignment.bottomCenter,
  223. child: Material(
  224. color: Colors.transparent,
  225. child: Container(
  226. decoration: const BoxDecoration(
  227. color: Colors.black12,
  228. shape: BoxShape.circle,
  229. ),
  230. margin: const EdgeInsets.all(25),
  231. child: IconButton(
  232. color: Colors.white,
  233. onPressed: () async {
  234. for (int i = 10; i > 0; i--) {
  235. await HapticFeedback.vibrate();
  236. }
  237.  
  238. XFile file = await controller.takePicture();
  239. widget.onCapture(file);
  240. },
  241. icon: const Icon(
  242. Icons.circle,
  243. ),
  244. iconSize: 72,
  245. ),
  246. ),
  247. ),
  248. ),
  249. ],
  250. );
  251. }
  252. }
  253.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement