123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- import 'dart:async';
- import 'package:eitc_erm_dental_flutter/funcs.dart';
- import 'package:eitc_erm_dental_flutter/sp_util.dart';
- import 'package:eitc_erm_dental_flutter/widget/count_down_text.dart';
- import 'package:eitc_erm_dental_flutter/widget/operation_button.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter_screenutil/flutter_screenutil.dart';
- ///视频操作视图
- class VideoOperationView extends StatefulWidget {
- final VideoOperationViewController controller;
- final void Function() onTakePhoto;
- final void Function() onStartRecord;
- final void Function() onStopRecord;
- final void Function() onStopVideo;
- final String area;
- const VideoOperationView(
- {super.key,
- required this.controller,
- required this.onTakePhoto,
- required this.onStartRecord,
- required this.onStopRecord,
- required this.onStopVideo,
- required this.area});
- @override
- State<VideoOperationView> createState() => _VideoOperationViewState();
- }
- class _VideoOperationViewState extends State<VideoOperationView> {
- late final CountDownTextController _countController =
- CountDownTextController(_onCount);
- ///是否正在倒计时
- bool _isCountingDown = false;
- ///录像时间
- int _recordingTime = 0;
- Timer? _recordingTimer;
- @override
- void initState() {
- super.initState();
- widget.controller._setCountController(_countController);
- widget.controller.recordingState.addListener(_onUpdateRecordingState);
- widget.controller.isCountingDown.addListener(_onUpdateIsCountingDown);
- }
- ///更新录像状态
- void _onUpdateRecordingState() {
- if (!mounted) {
- return;
- }
- setState(() {
- if (widget.controller.isRecording) {
- _recordingTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
- setState(() {
- _recordingTime = timer.tick;
- });
- });
- } else {
- _recordingTimer?.cancel();
- _recordingTime = 0;
- }
- });
- }
- ///更新倒计时状态
- void _onUpdateIsCountingDown() {
- setState(() {
- _isCountingDown = widget.controller.isCounting;
- });
- }
- @override
- void dispose() {
- super.dispose();
- _recordingTimer?.cancel();
- _countController.dispose();
- widget.controller.recordingState.removeListener(_onUpdateRecordingState);
- widget.controller.isCountingDown.removeListener(_onUpdateIsCountingDown);
- }
- @override
- Widget build(BuildContext context) {
- return Stack(
- children: [
- _getButtons(),
- _getCountHold(),
- ],
- );
- }
- ///获取倒计时,保持等
- Widget _getCountHold() {
- TextStyle? style =
- Theme.of(context).textTheme.titleMedium?.copyWith(color: Colors.white);
- return Align(
- alignment: Alignment.topCenter,
- child: Padding(
- padding: EdgeInsets.only(top: 10.h),
- child: Column(
- children: [
- SizedBox(
- height: 30.h,
- ),
- //静止不动提示
- Visibility(
- visible: _isCountingDown,
- child: Column(
- children: [
- Text(getS().pleaseHold, style: style),
- SizedBox(
- height: 10.h,
- ),
- //倒计时
- CountDownText(
- controller: _countController,
- textStyle: style,
- ),
- SizedBox(
- height: 10.h,
- ),
- ],
- )),
- //录像计时
- Visibility(
- visible: widget.controller.isRecording,
- child: Text(
- _getRecordingTimeStr(),
- style: style,
- )),
- Visibility(
- visible: widget.area.isNotEmpty && !widget.controller.isRecording,
- child: Text(
- textAlign: TextAlign.center,
- getS().takePhotoAreaHint(toothAreaTranslate(widget.area)),
- style: style),
- )
- ],
- ),
- ),
- );
- }
- ///获取录像时间文本
- String _getRecordingTimeStr() {
- Duration duration = Duration(seconds: _recordingTime);
- return "${"${duration.inMinutes}".padLeft(2, "0")}:${"${duration.inSeconds % 60}".padLeft(2, "0")}";
- }
- ///获取按钮
- Widget _getButtons() {
- return OrientationBuilder(builder: (ctx, orientation) {
- Alignment alignment = orientation == Orientation.landscape
- ? Alignment.centerRight
- : Alignment.bottomCenter;
- //拍照按钮
- Widget buttonCamera = OperationButton(
- text: getS().takePhoto,
- onTap: _takePhoto,
- child: const Icon(
- Icons.camera_alt_outlined,
- color: Colors.white,
- ));
- //录像按钮
- Widget buttonRecord = OperationButton(
- text: getS().record,
- onTap: () {
- if (widget.controller.isRecording) {
- _stopRecord();
- } else {
- _startRecord();
- }
- },
- child: Container(
- width: 17.5.r,
- height: 17.5.r,
- decoration: BoxDecoration(
- color:
- widget.controller.isRecording ? Colors.red : Colors.white,
- shape: BoxShape.circle),
- ));
- //根据横竖屏显示在不同位置
- return Align(
- alignment: alignment,
- child: Container(
- padding: orientation == Orientation.landscape
- ? EdgeInsets.only(right: 20.w)
- : EdgeInsets.only(bottom: 20.h),
- child: orientation == Orientation.landscape
- ? Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- buttonCamera,
- SizedBox(
- height: 40.h,
- ),
- buttonRecord,
- ],
- )
- : Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- buttonRecord,
- SizedBox(
- width: 40.w,
- ),
- buttonCamera,
- ],
- ),
- ),
- );
- });
- }
- ///拍照
- void _takePhoto() async {
- if (!await requestStoreagePermission()) {
- showToast(text: getS().storagePermissionRejectHint);
- return;
- }
- bool isDelay = await SpUtil.getEnableDelayShot();
- int delay = await SpUtil.getDelayShotTime();
- _countController.startCount(isDelay ? delay : 0);
- if (isDelay) {
- widget.controller.isCounting = true;
- }
- }
- ///开始录像
- void _startRecord() async {
- if (!await requestStoreagePermission()) {
- showToast(text: getS().storagePermissionRejectHint);
- return;
- }
- widget.onStartRecord();
- }
- ///停止录像
- void _stopRecord() {
- widget.onStopRecord();
- }
- ///关闭视频
- void _stopVideo() {
- widget.onStopVideo();
- widget.controller.isCounting = false;
- }
- ///拍照倒计时
- void _onCount(int tick, bool complete) {
- if (!complete) {
- return;
- }
- widget.onTakePhoto();
- widget.controller.isCounting = false;
- }
- }
- class VideoOperationViewController {
- CountDownTextController? _countController;
- ValueNotifier<bool>? _recordingState;
- ValueNotifier<bool> get recordingState =>
- _recordingState ??= ValueNotifier(false);
- ValueNotifier<bool>? _isCountingDown;
- ValueNotifier<bool> get isCountingDown =>
- _isCountingDown ??= ValueNotifier(false);
- void _setCountController(CountDownTextController controller) {
- _countController = controller;
- }
- void dispose() {
- _countController?.stopCount();
- _recordingState?.dispose();
- _recordingState = null;
- _isCountingDown?.dispose();
- _isCountingDown = null;
- }
- void updateRecordingState(bool isRecording) {
- if (recordingState.value == isRecording) {
- return;
- }
- recordingState.value = isRecording;
- }
- bool get isRecording => recordingState.value;
- bool get isCounting => isCountingDown.value;
- set isCounting(bool bo) => isCountingDown.value = bo;
- }
|