Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WKWebView displays content wrong after orientation change

I am fairly new to iOS development and I'm using a WKWebView to display a page that plays a video using the Vimeo Player. When the app starts up, it shows the view correctly, no matter what orientation it is currently in. However, once I change the orientation the view will either look zoomed in or has whitespace below the video.

The annoying thing about this is that it's not consistent. Sometimes the view displays correctly, sometimes it doesn't. If I try to zoom the view in or out or try to scroll when using the app it usually corrects itself, but even that does not seem to be 100% reliable.

Some screenshots (tested on iPad 2):

Landscape orientation (correct): Landscape orientation (correct)

Portrait orientation (correct): Portrait orientation (correct)

Landscape orientation (incorrect): Landscape orientation (incorrect)

Portrait orientation (incorrect): Portrait orientation (incorrect)

And the code used to produce this result:

import Foundation
import UIKit
import WebKit

class VideoViewController : UIViewController, WKScriptMessageHandler {

@IBOutlet var containerView : UIView! = nil
var webView: WKWebView?

override func loadView() {
    super.loadView()
    self.webView = WKWebView()
    let contentController = WKUserContentController();
    let scaleToFit = WKUserScript(source: "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width, initial-scale=1.0'); document.getElementsByTagName('head')[0].appendChild(meta);", injectionTime: WKUserScriptInjectionTime.AtDocumentStart, forMainFrameOnly: true)
    contentController.addUserScript(scaleToFit)
    contentController.addScriptMessageHandler(self, name: "callbackHandler")
    self.view = webView!
}

override func viewDidLoad() {
    super.viewDidLoad()
    refreshUI()
}

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

func refreshUI() {
    let url = NSURL(string: "https://photofactsacademy.nl/api/vp.asp?id=152839850")
    let requestObj = NSURLRequest(URL: url!)
    webView!.loadRequest(requestObj)
}

func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
    if(message.name == "callbackHandler") {
        print("JavaScript is sending a message \(message.body)")
    }
}
}

I looked through SO for WKWebView and orientation change and didn't find anything that helped me.

Your help is appreciated.

like image 733
Ionicawa Avatar asked Jan 27 '16 16:01

Ionicawa


3 Answers

Can you try this

wkWebView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
like image 63
anoop4real Avatar answered Nov 10 '22 07:11

anoop4real


I was able to solve this problem by injecting a javascript reload call like this:

Swift:

 func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animateAlongsideTransition(nil, completion: {
     //Reset Frame of Webview
     webView.evaluateJavaScript("location.reload();", completionHandler: nil)
}

Objective C:

-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    //Reset Frame of Webview
    [_webView evaluateJavaScript:@"location.reload();" completionHandler:^(id _Nullable obj, NSError * _Nullable error) {
        NSLog(@"error:%@", error);
    }];
}
like image 5
Robert Bentley Avatar answered Nov 10 '22 07:11

Robert Bentley


You don't need to reload the entire web page. You just need to reload its input views. Make sure you have set constraints to web view properly and then add below code while changing orientation.

   // Reload inputs so that webview can adjust its content according to orientation
     [self.webView reloadInputViews];
like image 2
Abdul Yasin Avatar answered Nov 10 '22 06:11

Abdul Yasin