1

To my understanding, a WKWebView cannot be created in a Storyboard. I had to create it programmatically in one of my instances of ViewController with the following code:

 override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        webView.navigationDelegate = self
        view = webView
 }

The problem I'm facing is I'd like to have a UILabel placed above webView, that spans the width of the device. Right below it, without any visible space, I'd want the webView placed. So, if my label is say, 20 pixels in height, the webView would technically be placed 21 pixels lower than where it is now.

In a Storyboard this is obviously a trivial task; how is it done programmatically?

ronatory
  • 7,156
  • 4
  • 29
  • 49
randombits
  • 47,058
  • 76
  • 251
  • 433

6 Answers6

3

André Slotta's Answer should work using Visual Format Language. I want to show another solution using NSLayoutAnchor (Hints are in the code comments). The third alternative would be NSLayoutConstraint. For more informations you get here an overview of all three options

import UIKit
import WebKit


class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

  var webView: WKWebView!
  var label: UILabel!

  override var prefersStatusBarHidden: Bool {
    return true
  }

  override func loadView() {
    super.loadView()

    setupLabel()

    let webViewConfiguration = WKWebViewConfiguration()
    webView = WKWebView(frame: .zero, configuration: webViewConfiguration)
    webView.translatesAutoresizingMaskIntoConstraints = false
    webView.uiDelegate = self
    webView.navigationDelegate = self
    let request = URLRequest(url: URL(string: "https://stackoverflow.com/")!)
    webView.load(request)

    view.addSubview(webView)

    // x, y, width and height of the web view
    webView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    // put the top anchor just below the bottom anchor of the label
    // with this the web view is directly below your label
    webView.topAnchor.constraint(equalTo: label.bottomAnchor).isActive = true
    webView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    webView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true  
  }

  func setupLabel() {
    label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    label.text = "label"
    label.backgroundColor = .gray
    label.textColor = .red
    view.addSubview(label)

    // x, y, width and height of the label
    label.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    label.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    label.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    // the height of your label (In your case 20 pixels)
    label.heightAnchor.constraint(equalToConstant: 20).isActive = true
  }
}

Result:

enter image description here

Community
  • 1
  • 1
ronatory
  • 7,156
  • 4
  • 29
  • 49
1

if you need a solution using constraints do something like this:

class ViewController: UIViewController {
    var label: UILabel!
    var webView: WKWebView!

    override var prefersStatusBarHidden: Bool {
        return true
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.backgroundColor = UIColor.lightGray
        label.text = "some text"

        let webViewConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webViewConfiguration)
        webView.translatesAutoresizingMaskIntoConstraints = false
        webView.backgroundColor = UIColor.darkGray

        let request = URLRequest(url: URL(string: "http://www.google.de")!)
        webView.load(request)

        view.addSubview(label)
        view.addSubview(webView)

        // horizontal constraints
        NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "|[label]|", options: [], metrics: nil, views: ["label": label]))
        NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "|[webView]|", options: [], metrics: nil, views: ["webView": webView]))

        // vertical constraints
        NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|[label][webView]|", options: [], metrics: nil, views: ["label": label, "webView": webView]))
    }
}

here is what it looks like:

screenshot

André Slotta
  • 13,774
  • 2
  • 22
  • 34
0

You could add the UILabel and WKWebView into a UIScrollView. Just disable the scrolling and bouncing on the webview and it should automatically adjust to the height of the webview.

David
  • 77
  • 2
  • 10
0

Instead of making the WKWebView the view of the view controller, make the WKWebView a subview of the viewController's view. You can do this in viewDidLoad of your view controller.

var webView: WKWebView!
let label = UILabel()

override func viewDidLoad() {
    super.viewDidLoad()

    let webConfiguration = WKWebViewConfiguration()
    webView = WKWebView(frame: .zero, configuration: webConfiguration)
    webView.uiDelegate = self
    webView.navigationDelegate = self
    view.addSubview(webView)

    ... // Other customization here
    view.addSubview(label)
}

Then in viewDidLayoutSubviews you can position the views manually

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    webView.frame = ...
    label.frame = ...

}
Darryl Johnson
  • 431
  • 3
  • 10
0

This code could be done in most of the ViewController's lifecycle, preferably when the view isn't rendered yet ( so either init, viewDidLoad, viewWillAppear ).

Place the UI label with height 20px and width to be screen width :

let label = UILabel(frame: CGRect(x: 0, y:0, width: view.frame.width, height: 20))
view.addSubview(label)

Place the WKWebView underneath, so the WKWebView origin's would be (0, 20), and the height would be ( screen height - 20 )

let wkWebView = WKWebView(frame: CGRect(x: 0, y:20, width: view.frame.width, height : view.frame.height - 20))
view.addSubview(wkWebView)

The view here is the view of the ViewController itself.

That's pretty much it ! You can layout view just by changing frame of the view itself and then add it as the subview of the main view. If you want flexible views, then you would had to implement some LayoutConstraint code by hand, which is much more complex than this.

0

If you are using MarkupKit, you could accomplish this as follows:

<LMColumnView spacing="0">
    <UILabel text="This is the label" textAlignment="center" backgroundColor="#eeeeee"/>
    <WKWebView id="webView" weight="1"/>
</LMColumnView>

enter image description here

Greg Brown
  • 3,168
  • 1
  • 27
  • 37