Xcode 6 Swift Wkwebview Keyboard Settings

Do you know how to zoom content in WKWebView like it does safari?

just use this

let js = "document.getElementsByTagName('body')[0].style.webkitTextSizeAdjust='200%'"//dual size
webView.evaluateJavaScript(js, completionHandler: nil)

Resize IOS WKWebView when keyboard appears

To solve this I added the following declarations to ViewController.h

int appH ; // device width
int appW ; // device height
int keyH ; // keyboard height
int topMargin ; // safe area size at top of screen
int bottomMargin ; // safe area size at bottom of screen
bool smallScreen ; // whether want to see status bar in landscape

I expect that I should have declared these as properties of my ViewController object, but that is noting to do with the answer

I then create the web view as follows

- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:(BOOL)animated];

NSString *deviceType = [UIDevice currentDevice].model;
smallScreen = [deviceType hasPrefix:@"iPhone"];

WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init];
[theConfiguration.userContentController addScriptMessageHandler:self name:@"MyApp"];
[theConfiguration.preferences setValue:@"TRUE" forKey:@"allowFileAccessFromFileURLs"];

// note that in viewDidLoad safeAreaInsets is set to zero
topMargin = [UIApplication sharedApplication].statusBarFrame.size.height ;
if (@available(iOS 11, *)) topMargin = self.view.safeAreaInsets.top ;
bottomMargin = 0 ;
if (@available(iOS 11, *)) bottomMargin = self.view.safeAreaInsets.bottom ;

int top = (smallScreen && appW > appH)? 0 : topMargin ;
int height = (smallScreen && appW > appH)? appH : appH - topMargin - bottomMargin ;

webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, top , appW, height) configuration:theConfiguration];
webView.navigationDelegate = self;
webView.UIDelegate = self;

I then react to changes in size as follows

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
// code here executes before rotation
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
// code here executes during rotation
appH = size.height ;
appW = size.width ;
int top = (smallScreen && appW > appH)? 0 : topMargin ;
int height = (smallScreen && appW > appH)? appH : appH - topMargin - bottomMargin ;
webView.frame = CGRectMake(0, top , appW, height);
}
completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
// code here executes after rotation
[webView evaluateJavaScript:@"IOSOrientationChanged()" completionHandler:nil];
}
];
}

I also register for notification of keyboard events as follows

    [[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];

And react to these in this way

- (void)keyboardWillShow: (NSNotification *) notif
{
keyH = [notif.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height ;
NSString *javascriptString ;
javascriptString = [NSString stringWithFormat:@"IOSKeyboardChanged(%d)",keyH];
[webView evaluateJavaScript:javascriptString completionHandler:nil];
}

- (void)keyboardWillHide: (NSNotification *) notif
{
[webView evaluateJavaScript:@"IOSKeyboardChanged(0)" completionHandler:nil];
}

In the above sections I have referred to two Javascript functions

IOSOrientationChanged redraws the app content based on the size of the screen found in window.innerWidth and window.innerHeight.

IOSKeyboard Changed does the same but uses window.innerHeight less the height of the keyboard (which is passed as the only parameter to it).

Points to note

  1. Do not react in javascript to window.onorientationchange or window.onresize
  2. I create a new frame for the web view on rotation but by doing this during the transition and then calling the javascript code on completion, it is good enough for me.
  3. I initially tried creating a new frame on completion, but this caused many problems for me due to the few milliseconds that this took and the need to add variable delays inside javascript to wait for it to happen.
  4. I also tried moving the new frame creation to before the rotation but this caused launch screen issues. Not shown above, I have a view inside view controller identical to my launch screen which is displayed on viewDidLoad to cover the time taken to load the html/css/javascript. This is removed when the javascript reports that it has been loaded.
  5. I do not need to create a new frame when the keyboard appears or is removed, I simply inform the javascript to not use the hidden area. I found creating new web view frames here had the same time delay issues as above.
  6. Note that this solution works when rotating the device with the keyboard is visible.

UPDATE IOS 13.3.1

After updating to this version, I found that the code above was insufficient to prevent the web view occasionally scrolling partially out of sight. Please note the "occasionally". Most of the time the code worked as it did previously, however the occasional issues were sufficient to warrant a fix and to do this I did the following :

  1. add to the ViewController interface statement

    UIScrollViewDelegate

  2. after creating the web view add the following line

    webView.scrollView.delegate = self ;

  3. also add

    • (void)scrollViewDidScroll:(UIScrollView *)scrollView

    {
    [scrollView setContentOffset:CGPointMake(0,0)];
    };

Extra space on WKWebView when keyboard is opened

Change the content inset of WKWebView's ScrollView:

@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardHeight = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
self.webViewController.wv.scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0 - keyboardHeight, right: 0)
}
}

And

@objc func keyboardWillHideß(notification: NSNotification) {
UIView.animate(withDuration: 0.2, animations: {
self.webViewController.wv.scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
})
}

WKWebView how to disable adjustedContentInset when keyboard is shown?

If you remove the observers which handles the keyboard from the WKWebView it stops adding the adjustedContentInset:

    NotificationCenter.default.removeObserver(self.webView, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
NotificationCenter.default.removeObserver(self.webView, name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.removeObserver(self.webView, name: UIResponder.keyboardWillHideNotification, object: nil)


Related Topics



Leave a reply



Submit