Flutter双视频互斥播放控制:播放时另一视频自动暂停及图标切换
实现双视频互斥播放及图标同步
核心思路
将两个视频的播放状态、控制器统一放在父组件中管理,通过状态变量跟踪当前播放的视频索引,触发播放时自动暂停另一个视频,同时同步更新播放/暂停图标。
具体实现步骤
1. 父组件中管理控制器与播放状态
在包含两个PageViewWidg的页面组件里,初始化两个VideoPlayerController,并维护currentPlayingIndex变量记录当前播放的视频下标(null表示都暂停)。
class DoubleVideoPage extends StatefulWidget { final String videoUrl1; final String videoUrl2; const DoubleVideoPage({super.key, required this.videoUrl1, required this.videoUrl2}); @override State<DoubleVideoPage> createState() => _DoubleVideoPageState(); } class _DoubleVideoPageState extends State<DoubleVideoPage> { late VideoPlayerController _controller1; late VideoPlayerController _controller2; int? _currentPlayingIndex; // 0:第一个视频,1:第二个视频,null:都暂停 @override void initState() { super.initState(); // 初始化视频控制器 _controller1 = VideoPlayerController.networkUrl(Uri.parse(widget.videoUrl1)) ..initialize().then((_) => setState(() {})); _controller2 = VideoPlayerController.networkUrl(Uri.parse(widget.videoUrl2)) ..initialize().then((_) => setState(() {})); } @override void dispose() { // 释放控制器避免内存泄漏 _controller1.dispose(); _controller2.dispose(); super.dispose(); } }
2. 实现互斥播放逻辑
添加播放/暂停切换方法,点击某个视频时,先暂停另一个视频,再切换当前视频的播放状态,同步更新currentPlayingIndex:
void _togglePlay(int index) { setState(() { if (_currentPlayingIndex == index) { // 点击的是正在播放的视频,执行暂停 index == 0 ? _controller1.pause() : _controller2.pause(); _currentPlayingIndex = null; } else { // 先暂停之前播放的视频 if (_currentPlayingIndex == 0) _controller1.pause(); if (_currentPlayingIndex == 1) _controller2.pause(); // 播放当前点击的视频 index == 0 ? _controller1.play() : _controller2.play(); _currentPlayingIndex = index; } }); }
3. 修改PageViewWidg接收外部状态与回调
让PageViewWidg不再单独管理控制器,改为接收外部传入的控制器、播放状态和点击回调:
class PageViewWidg extends StatelessWidget { final VideoPlayerController controller; final bool isPlaying; final VoidCallback onTogglePlay; const PageViewWidg({ super.key, required this.controller, required this.isPlaying, required this.onTogglePlay, }); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTogglePlay, child: Stack( alignment: Alignment.center, children: [ // 视频渲染区域 controller.value.isInitialized ? AspectRatio( aspectRatio: controller.value.aspectRatio, child: VideoPlayer(controller), ) : const Center(child: CircularProgressIndicator()), // 播放/暂停图标 if (!controller.value.isPlaying || !controller.value.isInitialized) Icon( isPlaying ? Icons.pause_circle : Icons.play_circle, size: 60, color: Colors.white, ), ], ), ); } }
4. 父组件中挂载修改后的PageViewWidg
将两个PageViewWidg传入对应的控制器、播放状态和回调:
@override Widget build(BuildContext context) { return Column( children: [ Expanded( child: PageViewWidg( controller: _controller1, isPlaying: _currentPlayingIndex == 0, onTogglePlay: () => _togglePlay(0), ), ), Expanded( child: PageViewWidg( controller: _controller2, isPlaying: _currentPlayingIndex == 1, onTogglePlay: () => _togglePlay(1), ), ), ], ); }
关键注意点
- 生命周期管理:必须在父组件的
dispose方法中释放两个控制器,防止内存泄漏 - 状态一致性:通过
_currentPlayingIndex统一控制播放状态,确保图标显示与实际播放状态同步 - 初始化判断:等待控制器初始化完成后再渲染视频,避免出现异常
内容的提问来源于stack exchange,提问作者oussama
相关产品推荐
相关产品推荐

