Make a UIWebView as height as its content with Auto Layout

只愿长相守 提交于 2019-12-04 07:46:25

问题


I've got a web view embedded in a scroll view, and I want the web view to be "expanded" to show all of its content, which I then want to scroll through with my scroll view.

The reason I am using a scroll View as a super view and not just using the web view as a scroll view is because I have labels above the web view that I want to include in the scrolling process (see screenshot).

So how do I make the webview resize itself so it takes up all the space it needs to show the content it contains ?

And after that, how do I make the superview (the Scroll view) resize itself according to the size of the webview?


回答1:


To make this work you have to do the following steps:

  1. Connect the UIWebView from the nib to an outlet in your view controller
  2. Disable scrolling in the web view
  3. Set the constraints on the UIScrollView, the UIView on top of the web view (In my example I omitted all the labels in that view) and the UIWebView.
  4. Connect the UIWebView's height constraint to an outlet in your view controller.
  5. Set the view controller as UIWebViewDelegate
  6. In webViewDidFinishLoad set the height constraint's constant to the height of the contentSize of the scroll view inside the web view.
  7. Start Key-Value Observing on the contentSize to change the height, when height of the web view has to change because segments of the webpage change their size without reloading the page (like accordeons, or menus).

I won't explain the constraints in detail as you seem to already have figured them out yourself. Here is a screenshot of the constraints:

So, here is the code:

import UIKit

var MyObservationContext = 0

class ViewController: UIViewController {

    @IBOutlet weak var webview: UIWebView!
    @IBOutlet weak var webviewHeightConstraint: NSLayoutConstraint!
    var observing = false

    override func viewDidLoad() {
        super.viewDidLoad()
        webview.scrollView.scrollEnabled = false
        webview.delegate = self
        webview.loadRequest(NSURLRequest(URL: NSURL(string: "https://www.google.de/intl/de/policies/terms/regional.html")!))
    }

    deinit {
        stopObservingHeight()
    }

    func startObservingHeight() {
        let options = NSKeyValueObservingOptions([.New])
        webview.scrollView.addObserver(self, forKeyPath: "contentSize", options: options, context: &MyObservationContext)
        observing = true;
    }

    func stopObservingHeight() {
        webview.scrollView.removeObserver(self, forKeyPath: "contentSize", context: &MyObservationContext)
        observing = false
    }

    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        guard let keyPath = keyPath else {
            super.observeValueForKeyPath(nil, ofObject: object, change: change, context: context)
            return
        }
        switch (keyPath, context) {
        case("contentSize", &MyObservationContext):
            webviewHeightConstraint.constant = webview.scrollView.contentSize.height
        default:
            super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
        }
    }
}

extension ViewController: UIWebViewDelegate {
    func webViewDidFinishLoad(webView: UIWebView) {
        print(webView.request?.URL)
        webviewHeightConstraint.constant = webview.scrollView.contentSize.height
        if (!observing) {
            startObservingHeight()
        }
    }
}



回答2:


Great solution from @joern. Works fine for me. I just adapted his code to swift 3.

Swift 3 Update Code :

I also modify stopObservingHeight to prevent remove observer before it was create.

import UIKit

var MyObservationContext = 0

class ViewController: UIViewController {

    @IBOutlet weak var webview: UIWebView!
    @IBOutlet weak var webviewHeightConstraint: NSLayoutConstraint!
    var observing = false

    override func viewDidLoad() {
        super.viewDidLoad()
        webview.scrollView.isScrollEnabled = false
        webview.delegate = self
        webview.loadRequest(NSURLRequest(URL: NSURL(string: "https://www.google.de/intl/de/policies/terms/regional.html")!))
    }

    deinit {
        stopObservingHeight()
    }

    func startObservingHeight() {
        let options = NSKeyValueObservingOptions([.new])
        webview.scrollView.addObserver(self, forKeyPath: "contentSize", options: options, context: &MyObservationContext)
        observing = true;
    }

    func stopObservingHeight() {
    if observing {
        webView.scrollView.removeObserver(self, forKeyPath: "contentSize", context: &MyObservationContext)            
        observing = false
    }
}

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    guard let keyPath = keyPath,
        let context = context else {
        super.observeValue(forKeyPath: nil, of: object, change: change, context: nil)
        return
    }
    switch (keyPath, context) {
    case("contentSize", &MyObservationContext):
        webviewHeightConstraint.constant = webview.scrollView.contentSize.height
    default:
        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
    }

}
}

extension ViewController: UIWebViewDelegate {
    func webViewDidFinishLoad(_ webView: UIWebView) {
        print(webView.request?.url ?? "nil")
        webviewHeightConstraint.constant = webview.scrollView.contentSize.height
        if (!observing) {
            startObservingHeight()
        }
    }
}


来源:https://stackoverflow.com/questions/33262575/make-a-uiwebview-as-height-as-its-content-with-auto-layout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!