import 'dart:io'; import 'package:audio_video_progress_bar/audio_video_progress_bar.dart'; import 'package:auto_route/auto_route.dart'; import 'package:eitc_erm_dental_flutter/entity/history_item_info.dart'; import 'package:eitc_erm_dental_flutter/funcs.dart'; import 'package:eitc_erm_dental_flutter/pages/history/vm/history_view_model.dart'; import 'package:eitc_erm_dental_flutter/pages/history/widget/history_view_title.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_vlc_player/flutter_vlc_player.dart'; import '../../app_router.gr.dart'; import 'widget/history_view_operation_view.dart'; ///视频播放页面 @RoutePage(name: "videoPlayerRoute") class VideoPlayerPage extends ConsumerStatefulWidget { final HistoryItemInfo? info; const VideoPlayerPage({super.key, required this.info}); @override ConsumerState createState() => _VideoPlayerPageState(); } class _VideoPlayerPageState extends ConsumerState { VlcPlayerController? _playerController; bool _playVisible = false; Duration _totalDuration = const Duration(); Duration _position = const Duration(); @override void initState() { super.initState(); //开启屏幕旋转 screenEnableRotate(); _initPlayerController(); } ///初始化视频控制器 void _initPlayerController() async { if (widget.info == null) { return; } _playerController = VlcPlayerController.file( File(widget.info!.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(); //关闭屏幕旋转 screenDisableRotate(); await _playerController?.stopRendererScanning(); _playerController?.dispose(); } @override Widget build(BuildContext context) { Widget videoView = (widget.info == null || _playerController == null) ? const SizedBox() : _getVideoView(); return Scaffold( body: SafeArea( child: Container( color: Colors.black, child: Stack( children: [ videoView, Align( alignment: Alignment.topLeft, child: HistoryViewTitle( name: widget.info?.name, ), ), HistoryViewOperationView( onUpload: () => _onUpload(context), onDelete: () => _onDelete(context), ), ], ), ), ), ); } 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 _onUpload(BuildContext context) async { if (!await checkInternetWifi()) { return; } if (context.mounted) { context.pushRoute(UploadSelectClinicRoute( uploadList: [widget.info!], isFromView: true)); } } void _onDelete(BuildContext context) async { if (widget.info == null) { return; } bool? bo = await showDeleteAlertDialog(context, getS().deleteVideoHint); if (bo == null || !bo) { return; } bool result = await ref.read(historyListProvider.notifier).delete([widget.info!]); if (result) { showToast(text: getS().deleteSuccess); if (context.mounted) { Navigator.pop(context, widget.info); } } else { showToast(text: getS().deleteFailed); } } }