Wkwebview Page Height Issue on iPhone X

make WKWebview real fullscreen on iPhone X (remove safe area from WKWebView

After a little try and error, this is the solution I came up with.
Subclass WKWebView and create a custom class. Overwrite safeAreaInsets:

import Foundation
import WebKit

class FullScreenWKWebView: WKWebView {
override var safeAreaInsets: UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}

iOS WKWebView Status Bar Padding

I solved this problem using autolayout constraints, Please check

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate {

var webView: WKWebView!

override func viewDidLoad() {
super.viewDidLoad()

setupWebView()

let url = URL(string: "https://www.google.com")
let request = URLRequest(url: url!)
webView.load(request)
}

func setupWebView() {
let webConfiguration = WKWebViewConfiguration()

webView = WKWebView(frame:.zero , configuration: webConfiguration)
webView.uiDelegate = self
//view = webView
view.addSubview(webView)
webView.translatesAutoresizingMaskIntoConstraints = false

view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":webView]))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-20-[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":webView]))
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Sample Image
Hope it helps.

WKWebView: document.body.offsetHeight returns wrong height, why?

You Need to add meta tag as follows

<meta name=\"viewport\" content=\"initial-scale=1, user-scalable=no, width=device-width\" />

Can't get WKWebView content height correctly

following method should do a trick

      //to get height

webView.evaluateJavaScript("document.height") { (result, error) in
if error == nil {
print(result)
}
}

//to get width
webView.evaluateJavaScript("document.width") { (result, error) in
if error == nil {
print(result)
}
}
// to get contentheight of wkwebview
func webView(webView: WKWebView!, didFinishNavigation navigation: WKNavigation!) {

println(webView.scrollView.contentSize.height)

}

How to adjust WKWebview's container content height to the webview content?

I think you are actually pretty close to a solution there. I've faced a similar problem and managed to solve it with evaluating javascript. Our implementation is a little bit different since we use a stackview with nested WkWebViews as arranged subviews. But I can share our code (stripped out the stackview parts) and you can try it out yourself.

    func addAndLoadWebView(with url: URL) {
let wkWebView = WKWebView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 100))
wkWebView.translatesAutoresizingMaskIntoConstraints = false
wkWebView.navigationDelegate = self
wkWebView.scrollView.isScrollEnabled = false
wkWebView.scrollView.bounces = false
wkWebView.scrollView.bouncesZoom = false
wkWebView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.view.addSubview(wkWebView)
wkWebView.load(URLRequest(url: url))
}

@available(iOS 12.0, *)
func asyncGetHTMLHeight(_ webview: WKWebView, completion: @escaping (CGFloat) -> Void) {
webview.evaluateJavaScript("document.body.offsetHeight") { (result, _) in
guard let result = result as? CGFloat else {
completion(0.0)
return
}
completion(result)
}
}

@available(iOS 12.0, *)
func compatibleMeasureImageContent(with webview: WKWebView) {
webview.evaluateJavaScript("document.body.firstChild.offsetHeight") { (result, _) in
guard let result = result as? CGFloat else {
return
}
var height = result
webview.evaluateJavaScript("document.body.firstChild.width") { (result, _) in
guard let width = result as? CGFloat else {
return
}
// do something with width and height here
// in our case images come 1 by one since our html is delivered in parts. You might have to check each image tag for its height for this calculation to work.
}
}
}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
self.asyncGetHTMLHeight(webView, completion: { newHeight in
webView.frame.size.height = newHeight
webView.removeConstraints(webView.constraints)
webView.heightAnchor.constraint(equalToConstant: newHeight).isActive = true
})
}

How to determine the content size of a WKWebView?

I think I read every answer on this subject and all I had was part of the solution. Most of the time I spent trying to implement KVO method as described by @davew, which occasionally worked, but most of the time left a white space under the content of a WKWebView container. I also implemented @David Beck suggestion and made the container height to be 0 thus avoiding the possibility that the problem occurs if the container height is larger that that of the content. In spite of that I had that occasional blank space.
So, for me, "contentSize" observer had a lot of flaws. I do not have a lot of experience with web technologies so I cannot answer what was the problem with this solution, but i saw that if I only print height in the console but do not do anything with it (eg. resize the constraints), it jumps to some number (e.g. 5000) and than goes to the number before that highest one (e.g. 2500 - which turns out to be the correct one). If I do set the height constraint to the height which I get from "contentSize" it sets itself to the highest number it gets and never gets resized to the correct one - which is, again, mentioned by @David Beck comment.

After lots of experiments I've managed to find a solution that works for me:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
self.webView.evaluateJavaScript("document.readyState", completionHandler: { (complete, error) in
if complete != nil {
self.webView.evaluateJavaScript("document.body.scrollHeight", completionHandler: { (height, error) in
self.containerHeight.constant = height as! CGFloat
})
}

})
}

Of course, it is important to set the constraints correctly so that scrollView resizes according to the containerHeight constraint.

As it turns out didFinish navigation method never gets called when I wanted, but having set document.readyState step, the next one (document.body.offsetHeight) gets called at the right moment, returning me the right number for height.

WKWebView not staying flush with status bar

From what I have seen in the images you posed, you don't have any layout constraints for the WebView, which I think explains what you are seeing. Without those constrains, the view will not be resized to fit various devices. Below is what I would suggest for constraints if you want things "flush" to top and bottom bars (important to place the constraint against the SafeArea). To add these constraints drag the web view to the edges of the display until you see the a dotted blue line and then click the button that looks like a tie-fighter (second button from right) and then click the red dotted |---| symbols to apply constraints in each direction.

Sample Image

This should give you layouts that look like this:

Sample Image

When running in the simulator, you get the the results shown below. You can see things look a bit different on the iPhone X devices, but this how things are designed on those devices to make sure the controls are accessible. One thing I did notice was that the grey area you see in Xcode for the web view, does not correctly move when you change the orientation or size of the device in Xcode. However, the edges of the display do move correctly so I would chalk that up to a bug Xcode.

Really hope that helps. I remember being very confused when it came to constraints when I first started. It takes a bit to get your head around things.

iPhone 8
iPhone 8
iPhone 8 landscape
iPhone8
iPad
iPad
iPad Landscape
iPad
iPhone X
iPhoneX
iPhone XR
iPhoneX



Related Topics



Leave a reply



Submit