import 'package:common_utils/common_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:video_player/video_player.dart'; import 'package:wow_english/common/extension/string_extension.dart'; import 'package:wow_english/pages/video/lookvideo/bloc/look_video_bloc.dart'; import 'package:wow_english/route/route.dart'; import 'video_opera_widget.dart'; class VideoWidget extends StatefulWidget { const VideoWidget({super.key, this.videoUrl = '',this.typeTitle, this.courseLessonId = '', this.isTopic = false}); final String videoUrl; final String? typeTitle; final String courseLessonId; final bool isTopic; @override State createState() { return _VideoWidgetState(); } } class _VideoWidgetState extends State { VideoPlayerController? _controller; String _currentTime = '00:00'; String _totalTime = '00:00'; double _playDegree = 0.0; bool _hiddenTipView = false; TimerUtil? timerUtil; String formatDuration(Duration duration) { String hours = duration.inHours.toString().padLeft(2, '0'); String minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0'); String seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0'); return "$hours:$minutes:$seconds"; } void _addListener() { _controller!.addListener(() { if(_controller!.value.isInitialized) { if (_controller!.value.isPlaying) { setState(() { double currentSecond = (_controller!.value.position.inMinutes.remainder(60)*60+_controller!.value.position.inSeconds.remainder(60)).toDouble(); int totalSecond = _controller!.value.duration.inMinutes.remainder(60)*60+_controller!.value.duration.inSeconds.remainder(60); _currentTime = formatDuration(_controller!.value.position); _playDegree = currentSecond/totalSecond; if (_playDegree > 1.0) { _playDegree = 1.0; } if(_playDegree < 0) { _playDegree = 0.0; } }); } else if (_controller!.value.isCompleted) { context.read().completeSection((){ String currentTime = (_controller!.value.position.inMinutes.remainder(60)*60+_controller!.value.position.inSeconds.remainder(60)).toString(); popPage(data:{'courseLessonId':widget.courseLessonId,'currentTime':currentTime, 'nextSection':widget.isTopic}); } as VoidCallback); } } }); } //开始倒计时 void startTimer() { if(timerUtil == null) { timerUtil = TimerUtil(mInterval: 1000,mTotalTime: 1000*10); timerUtil!.setOnTimerTickCallback((int tick) { double currentTick = tick / 1000; if (currentTick.toInt() == 0) {//倒计时结束 setState(() { _hiddenTipView = true; }); timerUtil!.cancel(); timerUtil = null; } }); timerUtil!.startCountDown(); } } //取消倒计时 void cancelTimer() { timerUtil!.cancel(); timerUtil = null; } void actionType(OperationType type) async { if (type == OperationType.back) { if (widget.courseLessonId.isEmpty) { popPage(); } else { if (_controller == null) { popPage(); return; } String currentTime = (_controller!.value.position.inMinutes.remainder(60)*60+_controller!.value.position.inSeconds.remainder(60)).toString(); popPage(data:{'courseLessonId':widget.courseLessonId,'currentTime':currentTime}); } } else if (type == OperationType.playState) { if (_controller!.value.isPlaying) { _controller!.pause(); } else { _controller!.play(); } setState(() { }); } } @override void initState() { super.initState(); Uri uri = Uri.parse(widget.videoUrl); _controller = VideoPlayerController.networkUrl(uri) ..initialize().then((_){ startTimer(); setState(() { _currentTime = formatDuration(_controller!.value.position); _totalTime = formatDuration(_controller!.value.duration); _controller!.setLooping(!widget.isTopic); _controller!.setVolume(100); _controller!.play(); }); _addListener(); }); } @override Widget build(BuildContext context) { return GestureDetector( onTap: () { setState(() { _hiddenTipView = !_hiddenTipView; if(!_hiddenTipView) { startTimer(); } else { if (timerUtil!.isActive()) { cancelTimer(); } } }); }, onDoubleTap: () { if(_controller!.value.isInitialized) { if (_controller!.value.isPlaying) { _controller!.pause(); } else { _controller!.play(); } setState(() { }); } }, child: Center( child: _controller!.value.isInitialized ? Stack( alignment: Alignment.center, children: [ SizedBox( height: double.infinity, width: double.infinity, child: AspectRatio( aspectRatio: _controller!.value.aspectRatio, child: VideoPlayer(_controller!), ), ), Offstage( offstage: _hiddenTipView, child: VideoOperaWidget( title: widget.typeTitle??'song', degree: _playDegree, totalTime: _totalTime, currentTime: _currentTime, isPlay: _controller!.value.isPlaying, actionEvent: (OperationType type) { actionType(type); }, sliderChangeEvent: (double degree) { int totalSecond = _controller!.value.duration.inMinutes.remainder(60)*60+_controller!.value.duration.inSeconds.remainder(60); int positionSecond = (totalSecond * degree).toInt(); _controller!.seekTo(Duration(seconds: positionSecond)); }, ), ), Offstage( offstage: _controller!.value.isPlaying, child: IconButton( onPressed: () { _controller!.play(); }, icon: Image.asset( 'video_stop'.assetPng, width: 70.w, height: 70.h, ), ), ) ], ): Container( color: Colors.white, child: Text( '视频加载中....', style: TextStyle( fontSize: 20.sp, color: Colors.black ), ), ), ), ); } @override void dispose() { _controller?.dispose(); _controller?.removeListener(() {}); if (timerUtil != null) { timerUtil!.cancel(); timerUtil = null; } super.dispose(); } }