import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; import 'package:flutter/services.dart'; ///弹窗组件:VideoPlayerPopup class VideoPlayerPopup extends StatefulWidget { /// 视频地址 final String videoUrl; const VideoPlayerPopup({Key? key, required this.videoUrl}) : super(key: key); @override State createState() => _VideoPlayerPopupState(); } class _VideoPlayerPopupState extends State { late VideoPlayerController _controller; bool _showControls = true; @override void initState() { super.initState(); _controller = VideoPlayerController.networkUrl( Uri.parse(widget.videoUrl), )..initialize().then((_) { setState(() {}); _controller.play(); }); // 自动隐藏控件 _controller.addListener(() { if (_controller.value.isPlaying && _showControls) { Future.delayed(const Duration(seconds: 3), () { if (_controller.value.isPlaying && mounted) { setState(() => _showControls = false); } }); } }); } @override void dispose() { _controller.dispose(); super.dispose(); } Widget _buildControls() { final pos = _controller.value.position; final dur = _controller.value.duration; String fmt(Duration d) => '${d.inMinutes.remainder(60).toString().padLeft(2, '0')}:' '${d.inSeconds.remainder(60).toString().padLeft(2, '0')}'; return Positioned.fill( child: AnimatedOpacity( opacity: _showControls ? 1 : 0, duration: const Duration(milliseconds: 300), child: GestureDetector( onTap: () => setState(() => _showControls = !_showControls), child: Container( color: Colors.black45, child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ // 进度条 Slider( value: pos.inMilliseconds.toDouble().clamp(0, dur.inMilliseconds.toDouble()), max: dur.inMilliseconds.toDouble(), onChanged: (v) { _controller.seekTo(Duration(milliseconds: v.toInt())); }, ), // 时间 + 控制按钮 Padding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: Row( children: [ IconButton( icon: Icon( _controller.value.isPlaying ? Icons.pause : Icons.play_arrow, color: Colors.white, ), onPressed: () { setState(() { _controller.value.isPlaying ? _controller.pause() : _controller.play(); }); }, ), Text( '${fmt(pos)} / ${fmt(dur)}', style: const TextStyle(color: Colors.white), ), const Spacer(), IconButton( icon: const Icon(Icons.fullscreen, color: Colors.white), onPressed: () { Navigator.of(context).push(MaterialPageRoute( builder: (_) => FullScreenVideoPage( controller: _controller))); }, ), ], ), ), ], ), ), ), ), ); } @override Widget build(BuildContext context) { return Center( child: Material( color: Colors.transparent, child: Container( constraints: BoxConstraints( maxWidth: MediaQuery.of(context).size.width * 0.9, maxHeight: MediaQuery.of(context).size.height * 0.8, ), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: Stack( children: [ // 视频内容 if (_controller.value.isInitialized) AspectRatio( aspectRatio: _controller.value.aspectRatio, child: VideoPlayer(_controller), ) else const Center(child: CircularProgressIndicator()), // 关闭按钮 Positioned( top: 4, right: 4, child: IconButton( icon: const Icon(Icons.close, color: Colors.black54), onPressed: () => Navigator.of(context).pop(), ), ), // 播放控制 if (_controller.value.isInitialized) _buildControls(), ], ), ), ), ); } } /// 全屏横屏播放页面:FullScreenVideoPage class FullScreenVideoPage extends StatefulWidget { final VideoPlayerController controller; const FullScreenVideoPage({Key? key, required this.controller}) : super(key: key); @override State createState() => _FullScreenVideoPageState(); } class _FullScreenVideoPageState extends State { VideoPlayerController get _controller => widget.controller; @override void initState() { super.initState(); // 进入横屏、沉浸式 SystemChrome.setPreferredOrientations([ DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight, ]); SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); } @override void dispose() { // 恢复竖屏 SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, body: Center( child: Stack( children: [ // 全屏视频 if (_controller.value.isInitialized) SizedBox.expand(child: VideoPlayer(_controller)) else const Center(child: CircularProgressIndicator()), // 简单控制:点击画面切换播放/暂停 GestureDetector( onTap: () { setState(() { _controller.value.isPlaying ? _controller.pause() : _controller.play(); }); }, ), // 返回按钮 Positioned( top: 20, left: 20, child: IconButton( icon: const Icon(Icons.arrow_back, color: Colors.white, size: 28), onPressed: () => Navigator.of(context).pop(), ), ), // 时间 & 进度条(简单版) if (_controller.value.isInitialized) Positioned( bottom: 20, left: 20, right: 20, child: Row( children: [ Text( '${_format(_controller.value.position)} / ${_format(_controller.value.duration)}', style: const TextStyle(color: Colors.white), ), const SizedBox(width: 12), Expanded( child: VideoProgressIndicator( _controller, allowScrubbing: true, colors: VideoProgressColors( playedColor: Colors.red, bufferedColor: Colors.white54, backgroundColor: Colors.white30, ), ), ), ], ), ), ], ), ), ); } String _format(Duration d) => '${d.inMinutes.remainder(60).toString().padLeft(2, '0')}:' '${d.inSeconds.remainder(60).toString().padLeft(2, '0')}'; }