Cordova-plugin-ionic-webview: Keyboard Dismissal Leaves Viewport Shifted in iOS 12 / XCode 10

Created on 22 Sep 2018  路  14Comments  路  Source: ionic-team/cordova-plugin-ionic-webview

I think it's a bug in ionic plugin (without the cordova-plugin-ionic-keyboard installed):
https://github.com/apache/cordova-ios/issues/417

Most helpful comment

Hi, I tried multiple things to get this fixed, including the CDVWKWebViewEngine.m thing above and tweaking options to the cordova-plugin-ionic-keyboard among other things. Finally, the only thing that helped was to download XCode 9.4, add iOS 12 device profiles and build using that version. According to initial testing, this seems to work on iOS 12 devices also on iPhone X.

All 14 comments

I have find why, in:
https://github.com/ionic-team/cordova-plugin-ionic-webview/blob/master/src/ios/CDVWKWebViewEngine.m
change line 38, 308 with
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 && __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
it's a bug in iOS 11 not in iOS 12, so running with iOS 12 the webview is not scrolled back to original position when keyboard is dismissed, line 79 and 310.

If you want to check also iPad (and this why on iPad was working with iOS 12 and mybe not working with iOS 11)
#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 && __IPHONE_OS_VERSION_MAX_ALLOWED < 120000) || (__IPAD_OS_VERSION_MAX_ALLOWED >= 110000 && __IPAD_OS_VERSION_MAX_ALLOWED < 120000)

Thanks so much @Stefano1964! I just discovered this pretty catastrophic bug today! I second your merge proposal 馃憤

please create a PR

The fix breaks the display in iPhone X and later models (XR, XS, and XS Max) for those that are using Ionic, where the extra spacing initially complained about when the keyboard disappears now becomes an issue as soon as the app is opened. The fix is an easy CSS change, at least for Ionic v1 apps:

.view, .view-container { height: calc(100% + env(safe-area-inset-top) + env(save-area-inset-bottom); }

At least it's now obvious where the extra spacing is coming from.

I am also witnessing the initial offset that the referenced patch creates in iPhoneX variants and can verify that @revie 's CSS tweak (applied to html element in our case) remedies that. However I'm not seeing the displacement fix actually work. Seems to have no effect on our app, leaving the viewport permanently offset after keyboard dismissal.

Hi, I tried multiple things to get this fixed, including the CDVWKWebViewEngine.m thing above and tweaking options to the cordova-plugin-ionic-keyboard among other things. Finally, the only thing that helped was to download XCode 9.4, add iOS 12 device profiles and build using that version. According to initial testing, this seems to work on iOS 12 devices also on iPhone X.

Changing CDVWKWebViewEngine.m worked for me except now the entire window height was off as mentioned above. The css for .view did not help, instead I did html { height: 100vh; } to solve the issue. BUT now platform.height() responds with the original height (which is of course incorrect)... It seems my hacky fix has just led to more issues. This is a pretty critical bug imo.. anyone else experiencing this or have a fix?

I've created a sample project with the bug https://github.com/jcesarmobile/webview-input-bug

It's a tabs project with an ion-input and a regular input. The bug is only reproducible when clicking the regular input, the ion-input internally manages the repositioning to avoid this kind of bugs.

This is a WKWebView bug on SDK 12, so the real fix can only be provided by Apple, or use some workaround, those are the options:

  1. Wait for Apple to fix it in a future release, it's already reported.
  2. Use Xcode 9 for now as it will use SDK 11 to compile and the bug is not present there.
  3. Use ion-input instead of regular input (only applicable if using Ionic)
  4. Install cordova-plugin-ionic-keyboard, any preference seems good in my sample as long as the plugin is installed. (might not work in non Ionic projects, didn't test there)

If not using Ionic and you think the linked PR fixes the problem there, provide a sample app. I've tested the PR changes in my project and didn't fix the problem.

Could use some testing on the above PR (#201) ^

cordova plugin add https://github.com/booleanbetrayal/cordova-plugin-ionic-webview.git#fix_ios_12_viewport

/cc @mobidev111 @jcesarmobile @NG-tylerholden @jkervine

 if #available(iOS 11.0, *) {
             self.webView.scrollView.contentInsetAdjustmentBehavior = .never
 } else {
            self.automaticallyAdjustsScrollViewInsets = false
 }

And UIScrollViewDelegate

 func scrollViewDidChangeAdjustedContentInset(_ scrollView: UIScrollView) {
       Logger.print("scrollViewDidChangeAdjustedContentInset")
         if #available(iOS 12.0, *) {
           for view in webView.subviews {
                if let scrollView = view as? UIScrollView {
                   scrollView.setContentOffset(.zero, animated: true)
                 }
             }
        }
}

Worked

This did work for me.

ViewController.h

@property (nonatomic) CGPoint lastContentOffset;

ViewController.m

- (void)viewDidLoad {    
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onKeyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}
- (void)onKeyboardWillShow:(NSNotification *)notification {
    self.lastContentOffset = self.webView.scrollView.contentOffset;
}
- (void)onKeyboardWillHide:(NSNotification *)notification {
    if (!CGPointEqualToPoint(self.lastContentOffset, self.webView.scrollView.contentOffset)) {
        [self.webView.scrollView setContentOffset:self.lastContentOffset];
        [self.webView.scrollView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
    }
     if (!CGPointEqualToPoint(self.lastContentOffset, self.webView.scrollView.contentOffset)) {
        [self.webView.scrollView setContentOffset:self.lastContentOffset];
        [self.webView.scrollView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
    }
}

I solve this bug with these command lines on app.components.ts:

let html = document.getElementsByTagName("html")[0];

 window.addEventListener('native.keyboardshow', (e) => {
      console.log("show2");
      html.style.height = "auto";
  });
window.addEventListener('native.keyboardhide', () => {
      console.log("hide2");
      html.style.height = "101vh";
});

This did work for me.

ViewController.h

@property (nonatomic) CGPoint lastContentOffset;

ViewController.m

- (void)viewDidLoad {    
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onKeyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}
- (void)onKeyboardWillShow:(NSNotification *)notification {
    self.lastContentOffset = self.webView.scrollView.contentOffset;
}
- (void)onKeyboardWillHide:(NSNotification *)notification {
    if (!CGPointEqualToPoint(self.lastContentOffset, self.webView.scrollView.contentOffset)) {
        [self.webView.scrollView setContentOffset:self.lastContentOffset];
        [self.webView.scrollView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
    }
     if (!CGPointEqualToPoint(self.lastContentOffset, self.webView.scrollView.contentOffset)) {
        [self.webView.scrollView setContentOffset:self.lastContentOffset];
        [self.webView.scrollView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
    }
}

Which ViewController.h and .m are you referring to? I dont see such files inside my cordova project folder. Also, just changing the keyboardwillhide and keyboardwillshow methods in CDVWKWebviewEngine inside the ionic-wk-webview-plugin files did fix the problem for ios13 but causes the viewport to have a bounce effect on ios 12 when shifting focus between text fields.

Was this page helpful?
0 / 5 - 0 ratings