WKWebView 在 iPad 上旋转后显示裁剪背景和空白 space
WKWebView shows a cropped background and blank space after rotation on iPad
我正在将我的应用程序从 UIWebView 迁移到 WKWebView 以供 iOS8.x(保持对 iOS7.x)用户的支持,我在显示的网站上遇到了问题,因为在旋转之后iPad,它显示了内容,但背景似乎被裁剪了,因此在 bg 之后有一个空白 space。
但是只要我开始滚动网站,它就会自动修复。当我从横向切换到纵向时,也会出现这种空白效果,这会使网站的右侧留下空白背景。
以下是我尝试解决问题的方法:
(void)willRotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation duration (NSTimeInterval)duration
{
[self.view setNeedsUpdateConstraints];
[_webView setNeedsUpdateConstraints];
}
(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[self.view setNeedsUpdateConstraints];
[_webView setNeedsUpdateConstraints];
}
我尝试了很多方法(通过 JS 重新加载后台,处理 willRotateToInterfaceOrientation 和 didRotateFromInterfaceOrientation 方法,如上所示)但未能解决问题,只有在使用 WKWebView 时才会出现,如果我切换回 UIWebView,网站会正确呈现 。
我还在同一台设备(iPad2 和 iOS 8.1.3)的 Safari 上测试了该网站,但无论我测试了多少次,它都没有显示错误旋转 iPad,所以我确定它可以解决 =)。有人可以帮我吗?
这是 WKWebKit 中的一个错误,通常由应用了 position: fixed
的 HTML 元素触发。我发现的唯一解决方法是使用 window.scrollTo()
在 resize
事件后几百毫秒将页面滚动一个像素。
我用document.head.appendChild(document.createElement('style')).remove();
在 resize/rotate.
之后让我的 WKWebViews 重新绘制
花了我一段时间,但我让它在没有滚动的页面上工作:
window.addEventListener('resize', function(){
setTimeout(function () {
var vp = document.getElementsByName("viewport")[0],
vpContent = vp.content,
vpHack = ((window.innerHeight > window.innerWidth) ? window.screen.availHeight / window.innerHeight : window.screen.availWidth / window.innerWidth) + 0.0001;
vp.content = "user-scalable=no, initial-scale="+vpHack+", maximum-scale="+vpHack+", minimum-scale="+vpHack+",width=device-width";
setTimeout(function(){vp.content=vpContent;},10);
}, 500);
}, true);
这是假设您使用视口。它将视口更改 0.0001,持续 10 毫秒
我是这样实现的:
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
NSLog(@"###### FINISH");
[self.webView evaluateJavaScript:[NSString stringWithFormat:@"if (document.readyState==='complete'){ window.addEventListener('resize', function(){setTimeout(function () {var vp = document.getElementsByName('viewport')[0],vpContent = vp.content,vpHack = ((window.innerHeight > window.innerWidth) ? window.screen.availHeight / window.innerHeight : window.screen.availWidth / window.innerWidth) + 0.0001; vp.content = 'user-scalable=no, initial-scale='+vpHack+', maximum-scale='+vpHack+', minimum-scale='+vpHack+',width=device-width';setTimeout(function(){vp.content=vpContent;},10);}, 500);}, true); } else { window.addEventListener('load', function(){window.addEventListener('resize', function(){setTimeout(function () {var vp = document.getElementsByName('viewport')[0],vpContent = vp.content,vpHack = ((window.innerHeight > window.innerWidth) ? window.screen.availHeight / window.innerHeight : window.screen.availWidth / window.innerWidth) + 0.0001; vp.content = 'user-scalable=no, initial-scale='+vpHack+', maximum-scale='+vpHack+', minimum-scale='+vpHack+',width=device-width';setTimeout(function(){vp.content=vpContent;},10);}, 500);}, true);}, false );}"] completionHandler:nil];
}
以下解决方法对我有用,但不幸的是只适用于模拟器:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
// Workaround for WKWebView iOS 8 Rotation Bug
// Official Fix (iOS 9): http://trac.webkit.org/changeset/169625
if ([[[UIDevice currentDevice] systemVersion] integerValue] == 8) {
CGRect frame = self.view.frame;
frame.size.width += 1;
self.view.frame = frame;
frame.size.width -= 1;
self.view.frame = frame;
}
}
经过一些试验后,我也通过以下步骤让它在设备上运行:
- 保留两组 AutoLayout 约束,第一个用于您实际想要的行为,第二个有一个小的变化(例如 1 点大小差异)
- 每当方向发生变化时,将第二组应用到视图,然后在 1 秒后应用第一组约束。
虽然这个解决方案远非理想,但它是我找到的唯一一个没有操纵网站上的 Javascript 的解决方案。我试图降低延迟,但在我的测试中我不得不等待至少 0.8 秒。
这救了我的命:
self.wkWebView.evaluateJavaScript("window.scrollBy(1, 1);window.scrollBy(-1, -1);", completionHandler: nil)
在 wkwebview 上添加这一行确实完成了导航事件!!
我正在将我的应用程序从 UIWebView 迁移到 WKWebView 以供 iOS8.x(保持对 iOS7.x)用户的支持,我在显示的网站上遇到了问题,因为在旋转之后iPad,它显示了内容,但背景似乎被裁剪了,因此在 bg 之后有一个空白 space。
但是只要我开始滚动网站,它就会自动修复。当我从横向切换到纵向时,也会出现这种空白效果,这会使网站的右侧留下空白背景。
以下是我尝试解决问题的方法:
(void)willRotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation duration (NSTimeInterval)duration
{
[self.view setNeedsUpdateConstraints];
[_webView setNeedsUpdateConstraints];
}
(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[self.view setNeedsUpdateConstraints];
[_webView setNeedsUpdateConstraints];
}
我尝试了很多方法(通过 JS 重新加载后台,处理 willRotateToInterfaceOrientation 和 didRotateFromInterfaceOrientation 方法,如上所示)但未能解决问题,只有在使用 WKWebView 时才会出现,如果我切换回 UIWebView,网站会正确呈现 。
我还在同一台设备(iPad2 和 iOS 8.1.3)的 Safari 上测试了该网站,但无论我测试了多少次,它都没有显示错误旋转 iPad,所以我确定它可以解决 =)。有人可以帮我吗?
这是 WKWebKit 中的一个错误,通常由应用了 position: fixed
的 HTML 元素触发。我发现的唯一解决方法是使用 window.scrollTo()
在 resize
事件后几百毫秒将页面滚动一个像素。
我用document.head.appendChild(document.createElement('style')).remove();
在 resize/rotate.
花了我一段时间,但我让它在没有滚动的页面上工作:
window.addEventListener('resize', function(){
setTimeout(function () {
var vp = document.getElementsByName("viewport")[0],
vpContent = vp.content,
vpHack = ((window.innerHeight > window.innerWidth) ? window.screen.availHeight / window.innerHeight : window.screen.availWidth / window.innerWidth) + 0.0001;
vp.content = "user-scalable=no, initial-scale="+vpHack+", maximum-scale="+vpHack+", minimum-scale="+vpHack+",width=device-width";
setTimeout(function(){vp.content=vpContent;},10);
}, 500);
}, true);
这是假设您使用视口。它将视口更改 0.0001,持续 10 毫秒
我是这样实现的:
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
NSLog(@"###### FINISH");
[self.webView evaluateJavaScript:[NSString stringWithFormat:@"if (document.readyState==='complete'){ window.addEventListener('resize', function(){setTimeout(function () {var vp = document.getElementsByName('viewport')[0],vpContent = vp.content,vpHack = ((window.innerHeight > window.innerWidth) ? window.screen.availHeight / window.innerHeight : window.screen.availWidth / window.innerWidth) + 0.0001; vp.content = 'user-scalable=no, initial-scale='+vpHack+', maximum-scale='+vpHack+', minimum-scale='+vpHack+',width=device-width';setTimeout(function(){vp.content=vpContent;},10);}, 500);}, true); } else { window.addEventListener('load', function(){window.addEventListener('resize', function(){setTimeout(function () {var vp = document.getElementsByName('viewport')[0],vpContent = vp.content,vpHack = ((window.innerHeight > window.innerWidth) ? window.screen.availHeight / window.innerHeight : window.screen.availWidth / window.innerWidth) + 0.0001; vp.content = 'user-scalable=no, initial-scale='+vpHack+', maximum-scale='+vpHack+', minimum-scale='+vpHack+',width=device-width';setTimeout(function(){vp.content=vpContent;},10);}, 500);}, true);}, false );}"] completionHandler:nil];
}
以下解决方法对我有用,但不幸的是只适用于模拟器:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
// Workaround for WKWebView iOS 8 Rotation Bug
// Official Fix (iOS 9): http://trac.webkit.org/changeset/169625
if ([[[UIDevice currentDevice] systemVersion] integerValue] == 8) {
CGRect frame = self.view.frame;
frame.size.width += 1;
self.view.frame = frame;
frame.size.width -= 1;
self.view.frame = frame;
}
}
经过一些试验后,我也通过以下步骤让它在设备上运行:
- 保留两组 AutoLayout 约束,第一个用于您实际想要的行为,第二个有一个小的变化(例如 1 点大小差异)
- 每当方向发生变化时,将第二组应用到视图,然后在 1 秒后应用第一组约束。
虽然这个解决方案远非理想,但它是我找到的唯一一个没有操纵网站上的 Javascript 的解决方案。我试图降低延迟,但在我的测试中我不得不等待至少 0.8 秒。
这救了我的命:
self.wkWebView.evaluateJavaScript("window.scrollBy(1, 1);window.scrollBy(-1, -1);", completionHandler: nil)
在 wkwebview 上添加这一行确实完成了导航事件!!