import 'dart:async'; import 'dart:io'; import 'dart:typed_data'; import 'package:camera/camera.dart'; import 'package:flutter/material.dart'; import 'package:image_editor/image_editor.dart'; import 'package:toko_kece/resources/themes.dart'; import 'package:toko_kece/resources/themes.dart'; import 'package:toko_kece/resources/themes.dart'; import 'package:toko_kece/resources/themes.dart'; import 'package:toko_kece/ui/components/camera/camera_timer_component.dart'; import 'package:toko_kece/ui/components/camera/custom_gallery_screen.dart'; import 'package:toko_kece/ui/components/loading_display_component.dart'; class CustomCameraComponent extends StatefulWidget { final bool videoMode; CustomCameraComponent({Key key, this.videoMode = false}) : super(key: key); @override _CustomCameraComponentState createState() => _CustomCameraComponentState(); } class _CustomCameraComponentState extends State<CustomCameraComponent> with WidgetsBindingObserver { CameraController _cameraController; List<CameraDescription> _cameras; int _cameraDesc = 0; File _videoRes; Future _initCamera(int index) async { _cameras = await availableCameras(); if (_cameras.length > 0) { _cameraController = CameraController(_cameras[index], ResolutionPreset.medium); } else { _cameraController = CameraController(_cameras[0], ResolutionPreset.medium); } await _cameraController.initialize(); } @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); // App state changed before we got the chance to initialize. if (_cameraController == null || !_cameraController.value.isInitialized) { return; } if (state == AppLifecycleState.inactive) { _cameraController?.dispose(); } else if (state == AppLifecycleState.resumed) { if (_cameraController != null) { setState(() {}); // rebuild } } } @override void dispose() { super.dispose(); _cameraController.dispose(); WidgetsBinding.instance.removeObserver(this); } Future<File> _takePicture() async { try { print("PRE-CAPTURE"); final xFile = await _cameraController.takePicture(); print("CAPTURED"); if (_cameras[_cameraDesc].lensDirection == CameraLensDirection.front) { // 1. read the image from disk into memory var file = File(xFile.path); Uint8List imageBytes = await file.readAsBytes(); // 2. flip the image on the X axis final ImageEditorOption option = ImageEditorOption(); option.addOption(FlipOption(horizontal: true)); imageBytes = await ImageEditor.editImage(image: imageBytes, imageEditorOption: option); // 3. write the image back to disk print("CAPTURED FRONT"); await file.delete(); return await file.writeAsBytes(imageBytes); } else { print("CAPTURED REAR"); return File(xFile.path); } } catch (e) { print("CAMERA ERROR : $e"); return null; } } Future<void> _takeVideo() async { try { await _cameraController.startVideoRecording(); } catch (e) { print("ERROR : $e"); } } Future<File> _stopVideoRecording() async { try { final xFile = await _cameraController.stopVideoRecording(); return File(xFile.path); } on CameraException catch (e) { print("ERROR : $e"); return null; } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, body: SafeArea( child: FutureBuilder( future: _initCamera(_cameraDesc), builder: (ctx, snap) { return snap.connectionState == ConnectionState.done ? StatefulBuilder( builder: (BuildContext c, StateSetter setMyState) { return Stack( children: [ Center( child: AspectRatio( aspectRatio: _cameraController.value.aspectRatio, child: CameraPreview(_cameraController), ), ), Align( alignment: Alignment.topCenter, child: Column( children: [ widget.videoMode && _cameraController.value.isRecordingVideo ? CameraTimerComponent( endByTimer: () async { _videoRes = await _stopVideoRecording(); _cameraController.dispose(); Navigator.of(context).pop(_videoRes); }, ) : Container( width: 0, height: 0, ), widget.videoMode ? Container() : _flashModeRowWidget(setMyState), ], ), ), Align( alignment: Alignment.bottomCenter, child: Container( margin: const EdgeInsets.only(bottom: 50), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ widget.videoMode ? Container( width: 80, height: 0, ) : RaisedButton( onPressed: () async { final result = await Navigator.of(context).push( MaterialPageRoute( builder: (_) => CustomGalleryScreen(), ), ) as File; if (result != null) { Navigator.of(context).pop(result); } }, clipBehavior: Clip.antiAlias, shape: CircleBorder(), color: Colors.white, child: Icon(Icons.image), ), Container( width: 80, height: 80, child: GestureDetector( onLongPress: () async { print("take video"); await _takeVideo(); setMyState(() {}); // refresh widget }, onLongPressUp: () async { _videoRes = await _stopVideoRecording(); _cameraController.dispose(); Navigator.of(context).pop(_videoRes); }, child: RaisedButton( onPressed: widget.videoMode ? null : () async { if (!_cameraController .value.isTakingPicture) { File result = await _takePicture(); Navigator.of(context) .pop(result); } }, clipBehavior: Clip.antiAlias, shape: CircleBorder( side: BorderSide( color: Colors.grey, width: 5, ), ), color: widget.videoMode ? _cameraController .value.isRecordingVideo ? Colors.red : Colors.white : Colors.white, ), ), ), RaisedButton( onPressed: () { setState(() { if (_cameraDesc == 0) _cameraDesc = 1; else _cameraDesc = 0; }); }, clipBehavior: Clip.antiAlias, shape: CircleBorder(), color: Colors.white, child: Icon(Icons.wifi_protected_setup), ), ], ), ), ), ], ); }, ) : LoadingDisplayComponent(); }, ), ), ); } Widget _flashModeRowWidget(setMyState) { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisSize: MainAxisSize.max, children: <Widget>[ IconButton( icon: const Icon(Icons.flash_off), color: _cameraController?.value?.flashMode == FlashMode.off ? primaryColor : Colors.grey.shade300, onPressed: _cameraController != null ? () => _onFlashModeButtonPressed(FlashMode.off, setMyState) : null, ), IconButton( icon: const Icon(Icons.flash_auto), color: _cameraController?.value?.flashMode == FlashMode.auto ? primaryColor : Colors.grey.shade300, onPressed: _cameraController != null ? () => _onFlashModeButtonPressed(FlashMode.auto, setMyState) : null, ), IconButton( icon: const Icon(Icons.flash_on), color: _cameraController?.value?.flashMode == FlashMode.always ? primaryColor : Colors.grey.shade300, onPressed: _cameraController != null ? () => _onFlashModeButtonPressed(FlashMode.always, setMyState) : null, ), ], ); } Future<void> _onFlashModeButtonPressed(FlashMode mode, setMyState) async { await _cameraController.setFlashMode(mode); setMyState(() {}); } }