diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f7e046..17e4769 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ To know more about breaking changes, see [Migration Guide][]. ### Improvements +- Improve the performance when taking photos. - Improve the experience when using the exposure slider. - Prefer `FlashMode.off` for better performance. - Allow `cameras` to be set repeatedly. diff --git a/lib/src/states/camera_picker_state.dart b/lib/src/states/camera_picker_state.dart index 0021769..89f5afc 100644 --- a/lib/src/states/camera_picker_state.dart +++ b/lib/src/states/camera_picker_state.dart @@ -56,12 +56,15 @@ class CameraPickerState extends State /// 可用的相机实例 late List cameras; + /// Whether the controller is handling taking picture or recording video. + /// 相机控制器是否在处理拍照或录像 + bool isControllerBusy = false; + /// Current exposure offset. /// 当前曝光值 final ValueNotifier currentExposureOffset = ValueNotifier(0); final ValueNotifier currentExposureSliderOffset = ValueNotifier(0); - double maxAvailableExposureOffset = 0; double minAvailableExposureOffset = 0; double exposureStep = 0; @@ -673,10 +676,17 @@ class CameraPickerState extends State pickerConfig.onError, ); } - if (controller.value.isTakingPicture) { + if (isControllerBusy) { return; } + isControllerBusy = true; + final ExposureMode previousExposureMode = controller.value.exposureMode; try { + await Future.wait(>[ + controller.setFocusMode(FocusMode.locked), + if (previousExposureMode != ExposureMode.locked) + controller.setExposureMode(ExposureMode.locked), + ]); final XFile file = await controller.takePicture(); await controller.pausePreview(); final bool? isCapturedFileHandled = pickerConfig.onXFileCaptured?.call( @@ -694,11 +704,17 @@ class CameraPickerState extends State Navigator.of(context).pop(entity); return; } + await Future.wait(>[ + controller.setFocusMode(FocusMode.auto), + if (previousExposureMode != ExposureMode.locked) + controller.setExposureMode(previousExposureMode), + ]); await controller.resumePreview(); } catch (e) { realDebugPrint('Error when preview the captured file: $e'); handleErrorWithHandler(e, pickerConfig.onError); } finally { + isControllerBusy = false; safeSetState(() {}); } } @@ -741,9 +757,10 @@ class CameraPickerState extends State /// Set record file path and start recording. /// 设置拍摄文件路径并开始录制视频 Future startRecordingVideo() async { - if (controller.value.isRecordingVideo) { + if (isControllerBusy) { return; } + isControllerBusy = true; try { await controller.startVideoRecording(); if (isRecordingRestricted) { @@ -756,6 +773,7 @@ class CameraPickerState extends State ..reset() ..start(); } catch (e, s) { + isControllerBusy = false; realDebugPrint('Error when start recording video: $e'); if (!controller.value.isRecordingVideo) { handleErrorWithHandler(e, pickerConfig.onError, s: s); @@ -824,6 +842,7 @@ class CameraPickerState extends State handleError(); handleErrorWithHandler(e, pickerConfig.onError, s: s); } finally { + isControllerBusy = false; safeSetState(() {}); } } @@ -973,7 +992,7 @@ class CameraPickerState extends State /// The button to switch flash modes. /// 切换闪光灯模式的按钮 Widget buildFlashModeSwitch(BuildContext context, CameraValue value) { - IconData icon; + final IconData icon; switch (value.flashMode) { case FlashMode.off: icon = Icons.flash_off;