123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- import 'dart:io';
- import 'package:audio_video_progress_bar/audio_video_progress_bar.dart';
- import 'package:auto_route/annotations.dart';
- import 'package:bot_toast/bot_toast.dart';
- import 'package:eitc_erm_dental_flutter/pages/view/widget/preview_operation_view.dart';
- import 'package:eitc_erm_dental_flutter/pages/view/widget/preview_title.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter_screenutil/flutter_screenutil.dart';
- import 'package:flutter_vlc_player/flutter_vlc_player.dart';
- import '../../entity/db/local_patient_info.dart';
- import '../../funcs.dart';
- import '../../global.dart';
- ///视频预览页面
- @RoutePage(name: "videoPreviewRoute")
- class VideoPreviewPage extends StatefulWidget {
- final LocalPatientInfo info;
- final String path;
- final String area;
- final DateTime time;
- final String mobile;
- final String wifi;
- final String deviceModel;
- const VideoPreviewPage(
- {super.key,
- required this.info,
- required this.path,
- required this.area,
- required this.time,
- required this.mobile,
- required this.wifi,
- required this.deviceModel});
- @override
- State<VideoPreviewPage> createState() => _VideoPreviewPageState();
- }
- class _VideoPreviewPageState extends State<VideoPreviewPage> {
- VlcPlayerController? _playerController;
- bool _playVisible = false;
- Duration _totalDuration = const Duration();
- Duration _position = const Duration();
- bool _isSaving = false;
- bool _isSaved = false;
- @override
- void initState() {
- super.initState();
- _initPlayerController();
- }
- ///初始化视频控制器
- void _initPlayerController() async {
- _playerController = VlcPlayerController.file(
- File(widget.path),
- hwAcc: HwAcc.auto,
- autoInitialize: true,
- autoPlay: true,
- options: VlcPlayerOptions(),
- );
- //循环播放,setLooping方法无效
- _playerController!.addListener(() async {
- VlcPlayerValue value = _playerController!.value;
- if (value.isInitialized && mounted) {
- //更新播放进度
- setState(() {
- _totalDuration = value.duration;
- _position = value.position;
- });
- }
- if (value.playingState == PlayingState.ended) {
- await _playerController!.stop();
- _playerController!.play();
- }
- });
- }
- @override
- void dispose() async {
- super.dispose();
- _deleteCache();
- await _playerController?.stopRendererScanning();
- _playerController?.dispose();
- }
- @override
- Widget build(BuildContext context) {
- Widget videoView =
- (_playerController == null) ? const SizedBox() : _getVideoView();
- return PopScope(
- canPop: !_isSaving,
- child: Scaffold(
- body: SafeArea(
- child: Container(
- color: Colors.black,
- child: Stack(
- children: [
- videoView,
- Align(
- alignment: Alignment.topLeft,
- child: PreviewTitle(
- title: getS().previewVideo,
- ),
- ),
- PreviewOperationView(
- onSave: _onSave,
- onCancel: _onCancel,
- ),
- ],
- ),
- ),
- ),
- ));
- }
- Widget _getVideoView() {
- return Stack(
- children: [
- GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: _onTap,
- child: Stack(
- children: [
- _getVideoPlayer(),
- _getPlayVisible(),
- ],
- ),
- ),
- _getSeekBar()
- ],
- );
- }
- Widget _getVideoPlayer() {
- return Container(
- color: Colors.black,
- alignment: Alignment.center,
- child: SizedBox.expand(
- child: AspectRatio(
- aspectRatio: _playerController!.value.aspectRatio,
- child: VlcPlayer(
- controller: _playerController!,
- aspectRatio: 16 / 9,
- placeholder: const Center(child: CircularProgressIndicator()),
- ),
- ),
- ),
- );
- }
- Widget _getPlayVisible() {
- return Align(
- alignment: Alignment.center,
- child: Visibility(
- visible: _playVisible,
- child: Icon(
- size: 100.r,
- Icons.play_circle_outline,
- color: Colors.white60,
- )),
- );
- }
- Widget _getSeekBar() {
- return Visibility(
- visible: _totalDuration != Duration.zero,
- child: Align(
- alignment: Alignment.bottomCenter,
- child: Padding(
- padding: EdgeInsets.only(bottom: 20.h, left: 20.w, right: 20.w),
- child: ProgressBar(
- progress: _position,
- total: _totalDuration,
- baseBarColor: Colors.white,
- thumbColor: Colors.white,
- timeLabelTextStyle: const TextStyle(color: Colors.white),
- timeLabelLocation: TimeLabelLocation.sides,
- onSeek: (duration) => _playerController!.seekTo(duration),
- ),
- ),
- ));
- }
- void _onTap() async {
- if (_playerController == null) {
- return;
- }
- bool? bo = await _playerController!.isPlaying();
- if (bo != null && bo) {
- await _playerController!.pause();
- setState(() {
- _playVisible = true;
- });
- } else {
- await _playerController!.play();
- setState(() {
- _playVisible = false;
- });
- }
- }
- void _onSave() async {
- logd("保存");
- setState(() {
- _isSaving = true;
- });
- var cancelFunc = BotToast.showLoading(clickClose: false, crossPage: false);
- try {
- await videoChannel.invokeMethod("saveRecord", [widget.path, widget.path]);
- _isSaved = true;
- cancelFunc();
- showToast(text: getS().saveSuccess);
- setState(() {
- _isSaving = false;
- });
- if (mounted) {
- Navigator.pop(context);
- }
- } catch (e) {
- setState(() {
- _isSaving = false;
- });
- cancelFunc();
- showToast(text: getS().saveFailed);
- loge("保存视频异常", error: e);
- }
- }
- void _onCancel() {
- logd("取消");
- Navigator.pop(context);
- }
- void _deleteCache() {
- if (widget.path.isEmpty || _isSaved) {
- return;
- }
- try {
- fileChannel.invokeMethod("deleteFile", widget.path);
- } catch (e) {
- loge("照片预览删除文件异常", error: e);
- }
- }
- }
|