2
2
/// [Author] Alex (https://github.com/AlexV525)
3
3
/// [Date] 2020/7/13 11:08
4
4
///
5
+ import 'dart:async' ;
5
6
import 'dart:io' ;
6
7
import 'dart:typed_data' ;
7
8
@@ -12,6 +13,9 @@ import 'package:path_provider/path_provider.dart';
12
13
import 'package:wechat_camera_picker/wechat_camera_picker.dart' ;
13
14
14
15
import '../constants/constants.dart' ;
16
+ import '../widget/circular_progress_bar.dart' ;
17
+
18
+ import 'builder/slide_page_transition_builder.dart' ;
15
19
16
20
/// Create a camera picker integrate with [CameraDescription] .
17
21
/// 通过 [CameraDescription] 整合的拍照选择
@@ -107,6 +111,10 @@ class CameraPicker extends StatefulWidget {
107
111
}
108
112
109
113
class _CameraPickerState extends State <CameraPicker > {
114
+ /// The [Duration] for record detection. (200ms)
115
+ /// 检测是否开始录制的时长 (200毫秒)
116
+ final Duration recordDetectDuration = kThemeChangeDuration;
117
+
110
118
/// Available cameras.
111
119
/// 可用的相机实例
112
120
List <CameraDescription > cameras;
@@ -127,6 +135,29 @@ class _CameraPickerState extends State<CameraPicker> {
127
135
/// 拍照文件的路径。
128
136
String takenFilePath;
129
137
138
+ /// Whether the [shootingButton] should animate according to the gesture.
139
+ /// 拍照按钮是否需要执行动画
140
+ ///
141
+ /// This happens when the [shootingButton] is being long pressed. It will animate
142
+ /// for video recording state.
143
+ /// 当长按拍照按钮时,会进入准备录制视频的状态,此时需要执行动画。
144
+ bool isShootingButtonAnimate = false ;
145
+
146
+ /// Whether the recording progress should display.
147
+ /// 视频录制的进度是否显示
148
+ ///
149
+ /// After [shootingButton] animated, the [CircleProgressBar] will become visible.
150
+ /// 当拍照按钮动画执行结束后,进度将变为可见状态并开始更新其状态。
151
+ bool isShowingProgress = false ;
152
+
153
+ /// The [Timer] for record start detection.
154
+ /// 用于检测是否开始录制的定时器
155
+ ///
156
+ /// When the [shootingButton] started animate, this [Timer] will start at the same
157
+ /// time. When the time is more than [recordDetectDuration] , which means we should
158
+ /// start recoding, the timer finished.
159
+ Timer recordDetectTimer;
160
+
130
161
/// Whether the current [CameraDescription] initialized.
131
162
/// 当前的相机实例是否已完成初始化
132
163
bool get isInitialized => controller? .value? .isInitialized ?? false ;
@@ -329,7 +360,7 @@ class _CameraPickerState extends State<CameraPicker> {
329
360
/// 该区域显示在屏幕下方。
330
361
Widget get shootingActions {
331
362
return SizedBox (
332
- height: Screens .width / 5 ,
363
+ height: Screens .width / 3. 5 ,
333
364
child: Row (
334
365
children: < Widget > [
335
366
Expanded (child: Center (child: backButton)),
@@ -368,21 +399,66 @@ class _CameraPickerState extends State<CameraPicker> {
368
399
/// 拍照按钮
369
400
// TODO(Alex): Need further integration with video recording.
370
401
Widget get shootingButton {
371
- return InkWell (
372
- borderRadius: maxBorderRadius,
373
- onTap: takePicture,
374
- child: Container (
375
- width: Screens .width / 5 ,
376
- height: Screens .width / 5 ,
377
- padding: const EdgeInsets .all (12.0 ),
378
- decoration: BoxDecoration (
379
- color: Colors .white30,
380
- shape: BoxShape .circle,
381
- ),
382
- child: const DecoratedBox (
383
- decoration: BoxDecoration (
384
- color: Colors .white,
385
- shape: BoxShape .circle,
402
+ final Size outerSize = Size .square (Screens .width / 3.5 );
403
+ return Listener (
404
+ behavior: HitTestBehavior .opaque,
405
+ onPointerUp: (PointerUpEvent event) {
406
+ recordDetectTimer? .cancel ();
407
+ if (isShowingProgress) {
408
+ isShowingProgress = false ;
409
+ if (mounted) {
410
+ setState (() {});
411
+ }
412
+ }
413
+ if (isShootingButtonAnimate) {
414
+ isShootingButtonAnimate = false ;
415
+ if (mounted) {
416
+ setState (() {});
417
+ }
418
+ }
419
+ },
420
+ child: InkWell (
421
+ borderRadius: maxBorderRadius,
422
+ onTap: () {},
423
+ onLongPress: () {
424
+ recordDetectTimer = Timer (recordDetectDuration, () {
425
+ isShowingProgress = true ;
426
+ if (mounted) {
427
+ setState (() {});
428
+ }
429
+ });
430
+ setState (() {
431
+ isShootingButtonAnimate = true ;
432
+ });
433
+ },
434
+ child: SizedBox .fromSize (
435
+ size: outerSize,
436
+ child: Stack (
437
+ children: < Widget > [
438
+ Center (
439
+ child: AnimatedContainer (
440
+ duration: kThemeChangeDuration,
441
+ width: isShootingButtonAnimate ? outerSize.width : (Screens .width / 5 ),
442
+ height: isShootingButtonAnimate ? outerSize.height : (Screens .width / 5 ),
443
+ padding: EdgeInsets .all (Screens .width / (isShootingButtonAnimate ? 10 : 35 )),
444
+ decoration: BoxDecoration (
445
+ color: Colors .white30,
446
+ shape: BoxShape .circle,
447
+ ),
448
+ child: const DecoratedBox (
449
+ decoration: BoxDecoration (
450
+ color: Colors .white,
451
+ shape: BoxShape .circle,
452
+ ),
453
+ ),
454
+ ),
455
+ ),
456
+ if (isShowingProgress) CircleProgressBar (
457
+ duration: 15. seconds,
458
+ outerRadius: outerSize.width,
459
+ ringsWidth: 2.0 ,
460
+ ),
461
+ ],
386
462
),
387
463
),
388
464
),
0 commit comments