Skip to content

Commit

Permalink
✨ Add enablePullToZoomInRecord
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexV525 committed Feb 25, 2021
1 parent 2e3ea86 commit 05a0dfd
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 18 deletions.
3 changes: 2 additions & 1 deletion README-ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ Flutter SDK:`>=1.20.0` 。
| ---------------------------- | ------------------------------ | ---------------------------------------------------------------- | -------------------------------------- |
| enableRecording | `bool` | 选择器是否可以录像 | `false` |
| onlyEnableRecording | `bool` | 选择器是否仅可以录像。只在 `enableRecording``true` 时有效。 | `false` |
| enabledAudio | `bool` | 选择器是否需要录制音频。只于录像配合有效。 | `true` |
| enableAudio | `bool` | 选择器是否需要录制音频。只于录像配合有效。 | `true` |
| enableSetExposure | `bool` | 用户是否可以在界面上通过点击设定曝光点 | `true` |
| enableExposureControlOnPoint | `bool` | 用户是否可以根据已经设置的曝光点调节曝光度 | `true` |
| enablePinchToZoom | `bool` | 用户是否可以在界面上双指缩放相机对焦 | `true` |
| enablePullToZoomInRecord | `bool` | 用户是否可以在录制视频时上拉缩放 | `true` |
| shouldDeletePreviewFile | `bool` | 返回页面时是否删除预览文件 | `false` |
| maximumRecordingDuration | `Duration` | 录制视频最长时长 | `const Duration(seconds: 15)` |
| theme | `ThemeData` | 选择器的主题 | `CameraPicker.themeData(C.themeColor)` |
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Reference:
| enableSetExposure | `bool` | Whether users can set the exposure point by tapping. | `true` |
| enableExposureControlOnPoint | `bool` | Whether users can adjust exposure according to the set point. | `true` |
| enablePinchToZoom | `bool` | Whether users can zoom the camera by pinch. | `true` |
| enablePullToZoomInRecord | `bool` | Whether users can zoom by pulling up when recording video. | `true` |
| shouldDeletePreviewFile | `bool` | Whether the preview file will be delete when pop. | `false` |
| maximumRecordingDuration | `Duration` | The maximum duration of the video recording process. | `const Duration(seconds: 15)` |
| theme | `ThemeData` | Theme data for the picker. | `CameraPicker.themeData(C.themeColor)` |
Expand Down
75 changes: 58 additions & 17 deletions lib/src/widget/camera_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class CameraPicker extends StatefulWidget {
this.enableSetExposure = true,
this.enableExposureControlOnPoint = true,
this.enablePinchToZoom = true,
this.enablePullToZoomInRecord = true,
this.shouldDeletePreviewFile = false,
this.maximumRecordingDuration = const Duration(seconds: 15),
this.theme,
Expand All @@ -47,6 +48,7 @@ class CameraPicker extends StatefulWidget {
assert(onlyEnableRecording != null),
assert(enableAudio != null),
assert(enablePinchToZoom != null),
assert(enablePullToZoomInRecord != null),
assert(enableSetExposure != null),
assert(enableExposureControlOnPoint != null),
assert(shouldDeletePreviewFile != null),
Expand Down Expand Up @@ -96,6 +98,10 @@ class CameraPicker extends StatefulWidget {
/// 用户是否可以在界面上双指缩放相机对焦
final bool enablePinchToZoom;

/// Whether users can zoom by pulling up when recording video.
/// 用户是否可以在录制视频时上拉缩放
final bool enablePullToZoomInRecord;

/// Whether the preview file will be delete when pop.
/// 返回页面时是否删除预览文件
final bool shouldDeletePreviewFile;
Expand Down Expand Up @@ -235,6 +241,10 @@ class CameraPickerState extends State<CameraPicker>
/// 最后一次手动聚焦的点坐标
final ValueNotifier<Offset> _lastExposurePoint = ValueNotifier<Offset>(null);

/// The last pressed position on the shooting button before starts recording.
/// 在开始录像前,最后一次在拍照按钮按下的位置
Offset _lastShootingButtonPressedPosition;

/// Current exposure mode.
/// 当前曝光模式
final ValueNotifier<ExposureMode> _exposureMode =
Expand Down Expand Up @@ -337,6 +347,8 @@ class CameraPickerState extends State<CameraPicker>

bool get enablePinchToZoom => widget.enablePinchToZoom;

bool get enablePullToZoomInRecord => widget.enablePullToZoomInRecord;

bool get shouldDeletePreviewFile => widget.shouldDeletePreviewFile;

/// Getter for `widget.maximumRecordingDuration` .
Expand Down Expand Up @@ -534,25 +546,33 @@ class CameraPickerState extends State<CameraPicker>
}
}

Future<void> zoom(double scale) async {
final double _zoom = (_baseZoom * scale)
.clamp(_minAvailableZoom, _maxAvailableZoom)
.toDouble();
if (_zoom == _currentZoom) {
return;
}
_currentZoom = _zoom;

await controller.setZoomLevel(_currentZoom);
}

/// Handle when the scale gesture start.
/// 处理缩放开始的手势
void _handleScaleStart(ScaleStartDetails details) {
_baseZoom = _currentZoom;
}

/// Handle when the scale details is updating.
/// 处理缩放更新
/// Handle when the double tap scale details is updating.
/// 处理双指缩放更新
Future<void> _handleScaleUpdate(ScaleUpdateDetails details) async {
// When there are not exactly two fingers on screen don't scale
if (_pointers != 2) {
return;
}

_currentZoom = (_baseZoom * details.scale)
.clamp(_minAvailableZoom, _maxAvailableZoom)
.toDouble();

await controller.setZoomLevel(_currentZoom);
zoom(details.scale);
}

void _restartPointDisplayTimer() {
Expand Down Expand Up @@ -644,6 +664,20 @@ class CameraPickerState extends State<CameraPicker>
_restartPointDisplayTimer();
}

void onShootingButtonMove(PointerMoveEvent event) {
_lastShootingButtonPressedPosition ??= event.position;
if (controller.value.isRecordingVideo) {
// First calculate relative offset.
final Offset _offset =
event.position - _lastShootingButtonPressedPosition;
// Then turn negative,
// multiply double with 10 * 1.5 - 1 = 14,
// plus 1 to ensure always scale.
final double _scale = _offset.dy / Screens.height * -14 + 1;
zoom(_scale);
}
}

/// The method to take a picture.
/// 拍照方法
///
Expand Down Expand Up @@ -696,6 +730,7 @@ class CameraPickerState extends State<CameraPicker>
void recordDetectionCancel(PointerUpEvent event) {
_recordDetectTimer?.cancel();
if (controller.value.isRecordingVideo) {
_lastShootingButtonPressedPosition = null;
stopRecordingVideo();
safeSetState(() {});
}
Expand Down Expand Up @@ -760,17 +795,22 @@ class CameraPickerState extends State<CameraPicker>
/// This displayed at the top of the screen.
/// 该区域显示在屏幕上方。
Widget get settingsAction {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Row(
children: <Widget>[
if ((cameras?.length ?? 0) > 1) switchCamerasButton,
const Spacer(),
_initializeWrapper(
builder: (CameraValue v, __) => switchFlashesButton(v),
return _initializeWrapper(
builder: (CameraValue v, __) {
if (v.isRecordingVideo) {
return const SizedBox.shrink();
}
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Row(
children: <Widget>[
if ((cameras?.length ?? 0) > 1) switchCamerasButton,
const Spacer(),
switchFlashesButton(v),
],
),
],
),
);
},
);
}

Expand Down Expand Up @@ -881,6 +921,7 @@ class CameraPickerState extends State<CameraPicker>
return Listener(
behavior: HitTestBehavior.opaque,
onPointerUp: enableRecording ? recordDetectionCancel : null,
onPointerMove: enablePullToZoomInRecord ? onShootingButtonMove : null,
child: InkWell(
borderRadius: maxBorderRadius,
onTap: !onlyEnableRecording ? takePicture : null,
Expand Down

0 comments on commit 05a0dfd

Please sign in to comment.