如何在Flutter的flutter_inappwebview中添加UC浏览器式内嵌视频播放器?
基于flutter_inappwebview实现UC风格内嵌视频播放器
下面是具体的实现步骤,覆盖核心功能点:
1. 配置WebView支持内嵌媒体播放
首先在InAppWebView的初始化配置中开启内嵌播放权限,避免视频跳转到系统播放器:
InAppWebViewGroupOptions( crossPlatform: InAppWebViewOptions( allowsInlineMediaPlayback: true, // 强制内嵌播放 mediaPlaybackRequiresUserGesture: false, // 可选:允许自动播放 ), android: AndroidInAppWebViewOptions( useHybridComposition: true, // 提升Android端播放性能 mediaPlaybackRequiresUserGesture: false, ), ios: IOSInAppWebViewOptions( allowsInlineMediaPlayback: true, ), )
2. 监听网页中的视频元素
通过注入JavaScript捕获页面内的<video>元素状态,同步到Flutter端:
在onWebViewCreated回调中添加JS监听和处理逻辑:
// 注册Flutter与JS的通信 handler controller.addJavaScriptHandler( handlerName: 'videoStatus', callback: (args) { final videoUrl = args[0] as String; final isPlaying = args[1] as bool; // 这里触发自定义播放器的显示/隐藏逻辑 if (isPlaying) { // 显示自定义内嵌播放器 showCustomVideoPlayer(context, videoUrl); } }, ); // 注入监听视频播放的JS代码 controller.evaluateJavascript(source: """ document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('video').forEach(video => { video.addEventListener('play', () => { window.flutter_inappwebview.callHandler('videoStatus', video.currentSrc, true); }); // 可选:监听暂停事件隐藏播放器 video.addEventListener('pause', () => { window.flutter_inappwebview.callHandler('videoStatus', video.currentSrc, false); }); }); }); """);
3. 实现自定义内嵌/悬浮播放器
用Flutter原生组件或第三方播放器库(如chewie、video_player)打造UC风格的播放器,支持小窗悬浮、拖拽:
// 示例:基于chewie的自定义播放器 class UCVideoPlayer extends StatefulWidget { final String videoUrl; const UCVideoPlayer({super.key, required this.videoUrl}); @override State<UCVideoPlayer> createState() => _UCVideoPlayerState(); } class _UCVideoPlayerState extends State<UCVideoPlayer> { late VideoPlayerController _videoController; late ChewieController _chewieController; @override void initState() { super.initState(); _videoController = VideoPlayerController.network(widget.videoUrl); _chewieController = ChewieController( videoPlayerController: _videoController, autoPlay: true, looping: false, customControls: const UCVideoControls(), // 自定义播放控件栏 ); } @override void dispose() { _videoController.dispose(); _chewieController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { // 用Draggable实现悬浮拖拽 return Draggable( feedback: _buildPlayer(), childWhenDragging: const SizedBox.shrink(), child: _buildPlayer(), ); } Widget _buildPlayer() { return Container( width: 320, height: 180, decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)), child: Chewie(controller: _chewieController), ); } } // 自定义控件栏,模拟UC的样式 class UCVideoControls extends StatelessWidget { const UCVideoControls({super.key}); @override Widget build(BuildContext context) { return Stack( children: [ // 播放/暂停按钮、进度条、全屏按钮等 // 这里根据需求自定义UI ], ); } }
4. 拦截系统播放器跳转
部分网页会强制唤起系统播放器,需要在shouldOverrideUrlLoading中拦截视频链接:
shouldOverrideUrlLoading: (controller, navigationAction) async { final uri = navigationAction.request.url; if (uri != null && ['mp4', 'm3u8', 'webm'].any(ext => uri.path.endsWith('.$ext'))) { // 拦截视频链接,用自定义播放器打开 showCustomVideoPlayer(context, uri.toString()); return NavigationActionPolicy.CANCEL; } return NavigationActionPolicy.ALLOW; },
5. 移动端权限与配置
- Android:在
AndroidManifest.xml添加权限
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- 保持屏幕常亮 -->
- iOS:在
Info.plist中允许非HTTPS媒体加载(如果需要)
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
内容的提问来源于stack exchange,提问作者Hamza Kaleem
相关产品推荐
相关产品推荐

