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 上添加这一行确实完成了导航事件!!