iOS WKWebView加载YouTube嵌入视频尺寸异常 仅显示1/4屏幕
问题场景
- 业务需求:从服务端拉取YouTube视频链接,用户在UITableView列表选中对应单元格后,跳转至下级页面自动播放选中的视频。
- 实现方案:采用WKWebView加载自定义HTML字符串的方式接入YouTube iFrame播放器,初始核心实现代码如下:
@IBOutlet weak var youtubeWebview: WKWebView! override func viewDidLoad() { super.viewDidLoad() self.loadWebView() } func loadWebView() { var embedVideoHtml:String { return """ <!DOCTYPE html> <html> <body> <!-- 1. The <iframe> (and video player) will replace this <div> tag. --> <div id="player"></div> <script> var tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); var player; function onYouTubeIframeAPIReady() { player = new YT.Player('player', { height: '\(youtubeWebview.frame.height)', width: '\(youtubeWebview.frame.width)', videoId: '\(videoLinkId)', events: { 'onReady': onPlayerReady } }); } function onPlayerReady(event) { event.target.playVideo(); } </script> </body> </html> """ } if !self.didLoadVideo { self.didLoadVideo = true self.youtubeWebview.loadHTMLString(embedVideoHtml, baseURL: nil) } }
- 异常表现:实际运行后视频仅占屏幕1/4大小,未达到「视频尺寸完全匹配承载WKWebView组件大小」的预期效果。
问题根因
两个核心问题导致尺寸异常:
- 加载时机错误:在
viewDidLoad中调用加载逻辑时,WKWebView尚未完成Auto Layout布局,此时获取的youtubeWebview.frame.height/width是xib/Storyboard中的初始尺寸,不是最终渲染到屏幕上的实际尺寸,硬编码写入HTML的播放器宽高本身就是错误值。 - HTML缺少适配样式:自定义HTML未做全局样式重置,body、div标签默认存在内外边距,且播放器容器未设置撑满父视图的样式规则,进一步导致播放器尺寸偏小。
修复方案
按以下步骤调整即可解决尺寸问题:
- 改写自定义HTML模板,增加全局样式重置,播放器宽高不硬编码数值,改用100%相对单位适配容器尺寸,修正后的HTML模板如下:
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <style> * { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; overflow: hidden; } #player { width: 100%; height: 100%; } </style> </head> <body> <div id="player"></div> <script> var tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); var player; function onYouTubeIframeAPIReady() { player = new YT.Player('player', { height: '100%', width: '100%', videoId: '\(videoLinkId)', events: { 'onReady': onPlayerReady } }); } function onPlayerReady(event) { event.target.playVideo(); } </script> </body> </html>
- 调整原生端加载时机,将WebView加载逻辑从
viewDidLoad移至viewDidLayoutSubviews中,保留单次加载判断,确保WKWebView布局完成后再加载内容,同时关闭WebView滚动相关属性避免出现多余滚动条,修正后的原生代码参考:
@IBOutlet weak var youtubeWebview: WKWebView! override func viewDidLoad() { super.viewDidLoad() // 关闭滚动、弹跳效果,避免出现多余交互 youtubeWebview.scrollView.isScrollEnabled = false youtubeWebview.scrollView.bounces = false } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() loadWebView() } func loadWebView() { let embedVideoHtml = """ // 替换为上述修正后的完整HTML模板 """ if !self.didLoadVideo { self.didLoadVideo = true self.youtubeWebview.loadHTMLString(embedVideoHtml, baseURL: nil) } }
- 检查WKWebView的约束设置,确保其上下左右约束与布局预期一致,不存在约束缺失导致WebView本身尺寸异常的问题。
内容的提问来源于stack exchange,提问作者Anilkumar iOS Developer
相关产品推荐
相关产品推荐

