Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keyboard Dismissal Leaves Viewport Shifted in iOS 12 / XCode 10 #417

Open
booleanbetrayal opened this issue Sep 20, 2018 · 115 comments
Open

Keyboard Dismissal Leaves Viewport Shifted in iOS 12 / XCode 10 #417

booleanbetrayal opened this issue Sep 20, 2018 · 115 comments

Comments

@booleanbetrayal
Copy link

@booleanbetrayal booleanbetrayal commented Sep 20, 2018

Seeing a blocking issue after updating to XCode 10 related to keyboard displacement and then dismissal.

When an input that would require webview centering is clicked, the viewport is repositioned to center that input, as iOS has traditionally done. However, when dismissing the keyboard, the viewport is not re-positioned properly back to its original position.

This can leave large gaps where the webview is no longer visible. In the attached screenshots, you can see that this leaves a large margin where the viewport is rendering, shifted upwards and off-screen by a 100+ pixels. There appears to be no way do re-position the viewport short of additional input focus changes, each resulting in similar offset issues.

To add some additional confusion, it appears this only happens on iOS 12 / XCode 10 produced installs, such that:

  • This issue is present ONLY on builds produced in XCode 10 targeting iOS 12 devices.
  • This issue affects ALL tested device types on iOS 12.
  • This issue is present via Legacy AND Modern build systems
  • iOS 10 / 11 devices targeted via XCode 10 are NOT affected.
  • iOS 10 / 11 / 12 devices targeted via XCode 9 are NOT affected.

Any info on potential workarounds or patches would be greatly appreciated. I've already looked into upgrading our cordova-plugin-ionic-webview plugin (as well as various others), but it appears to not have any relevance with the issue. At this point, we're looking at downgrading XCode in order to get working builds out.


Click Here to See Example Screenshots

Captured via iOS Simulator, but also experienced on various physical devices running iOS 12

Prior to focusing an input:
1

Input focused: / keyboard present
2

Keyboard dismissed / HTML element highlighted in inspector:
3


Click Here for Environment Details

OS: OSX 10.13.6 (High Sierra)
XCode: 10.0 (10A255)
cordova: 8.0.0
cordova-ios: 4.5.4
cordova-plugins:

  • cordova-android-support-gradle-release 1.2.0 "cordova-android-support-gradle-release"
  • cordova-custom-config 5.0.2 "cordova-custom-config"
  • cordova-plugin-app-event 1.2.1 "Application Events"
  • cordova-plugin-apprate 1.4.0 "AppRate"
  • cordova-plugin-camera 4.0.3 "Camera"
  • cordova-plugin-device 2.0.1 "Device"
  • cordova-plugin-dialogs 2.0.1 "Notification"
  • cordova-plugin-facebook4 1.9.1 "Facebook Connect"
  • cordova-plugin-file 6.0.1 "File"
  • cordova-plugin-googleplus 5.2.1 "Google SignIn"
  • cordova-plugin-inappbrowser 2.0.2 "InAppBrowser"
  • cordova-plugin-ionic-webview 1.1.16 "cordova-plugin-ionic-webview"
  • cordova-plugin-market 1.2.0 "Market"
  • cordova-plugin-media 4.0.1-dev "Media"
  • cordova-plugin-nativestorage 2.3.2 "NativeStorage"
  • cordova-plugin-network-information 2.0.1 "Network Information"
  • cordova-plugin-spinner-dialog 1.3.1 "SpinnerDialog"
  • cordova-plugin-splashscreen 5.0.3-dev "Splashscreen"
  • cordova-plugin-whitelist 1.3.3 "Whitelist"
  • cordova-plugin-x-socialsharing 5.3.2 "SocialSharing"
  • cordova-support-google-services 1.1.0 "cordova-support-google-services"
  • de.appplant.cordova.plugin.local-notification 0.8.5 "LocalNotification"
  • es6-promise-plugin 4.2.2 "Promise"
  • phonegap-plugin-multidex 1.0.0 "Multidex"
  • phonegap-plugin-push 2.2.3 "PushPlugin"

@project-bot project-bot bot added this to new/unassigned/reopened issues in Apache Cordova: project-bot automation testing Sep 20, 2018
@project-bot project-bot bot moved this from new/unassigned/reopened issues to edited issue in Apache Cordova: project-bot automation testing Sep 20, 2018
@janpio janpio added the bug label Sep 20, 2018
@dpogue

This comment has been minimized.

Copy link
Member

@dpogue dpogue commented Sep 20, 2018

Does this happen in a plain Cordova app without the Ionic WebView plugin? Does it happen if you use the Apache version of the WKWebView plugin (cordova-plugin-wkwebview-engine)?

@booleanbetrayal

This comment has been minimized.

Copy link
Author

@booleanbetrayal booleanbetrayal commented Sep 20, 2018

@dpogue - I AM seeing this when replacing cordova-plugin-ionic-webview with the cordova-plugin-wkwebview-engine WKWebView implementation, but I AM NOT seeing this without WKWebView (UIWebView)

@dpogue

This comment has been minimized.

Copy link
Member

@dpogue dpogue commented Sep 20, 2018

Are you using viewport-fit=cover in your meta viewport tag?

I'm trying to reproduce this in an iOS 12 simulator with Xcode 10 and plain WKWebView, and I don't see it doing anything different than iOS 11, but that might also be because my page scrolls.

@booleanbetrayal

This comment has been minimized.

Copy link
Author

@booleanbetrayal booleanbetrayal commented Sep 20, 2018

We are for iPhoneX / notch support:

<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi, viewport-fit=cover" />

I'm not seeing the issue when removing the viewport-fit=cover but this breaks notch workarounds of course.

@dpogue

This comment has been minimized.

Copy link
Member

@dpogue dpogue commented Sep 20, 2018

Okay, I've managed to reproduce it. The bad news is that it's not a Cordova bug, because I reproduced it in a demo Swift app with a standard WKWebView.

I'll try to wrap this demo up as a reduced test case and submit it to Apple 😞

Screenshots from my test

simulator screen shot - iphone xs max - 2018-09-20 at 13 50 44
simulator screen shot - iphone xs max - 2018-09-20 at 13 50 49
simulator screen shot - iphone xs max - 2018-09-20 at 13 50 54

@booleanbetrayal

This comment has been minimized.

Copy link
Author

@booleanbetrayal booleanbetrayal commented Sep 20, 2018

Was afraid of that. Thanks for confirmation / isolation @dpogue . If you link the issue here, I'll be sure to try and weigh in on its importance, etc.

@dpogue

This comment has been minimized.

Copy link
Member

@dpogue dpogue commented Sep 20, 2018

Radar filed as rdar://44655885
Mirrored at https://openradar.appspot.com/radar?id=5018321736957952
WebKit bug report at https://webkit.org/b/192564

Please file duplicate radar reports at http://bugreporter.apple.com!

@Stefano1964

This comment has been minimized.

Copy link

@Stefano1964 Stefano1964 commented Sep 22, 2018

In one af my app i had to use the ionic wkwebview (i dont use ionic framework) as this version allow to access files outside the app directory and the standard cordova wkwebview doesn't allow this kind of access.
I can see this bug ONLY with ionic wkwebview latest (Xcode 10, iOS 12 real device) and only on smartphone, on iPad it's ok (webview back to original position), on the same app switching to default cordova wkwebview the bug is not there.
Tested also with xs in simulator, same, with cordova wkwebview it's ok, not with ionic wkwebview.
@dpogue you provide a swift project (tested and the bug is present), but wkwebview implementation both in cordova and ionic is an obj-c implemenation, maybe a swift bug?

@Bravo2x

This comment has been minimized.

Copy link

@Bravo2x Bravo2x commented Sep 26, 2018

Hello! In my case i updated cordova-plugin-ionic-webview up to ="^2.1.4"
and ionic platform to latest version. For now i have

Ionic:

ionic (Ionic CLI) : 4.1.2 (/usr/local/lib/node_modules/ionic)
Ionic Framework : ionic-angular 3.9.2
@ionic/app-scripts : 3.1.11

Cordova:

cordova (Cordova CLI) : 8.0.0
Cordova Platforms : ios 4.5.5
Cordova Plugins : cordova-plugin-ionic-keyboard 2.1.2, cordova-plugin-ionic-webview 2.1.4, (and 12 other plugins)

System:

ios-sim : 5.0.13
NodeJS : v8.11.3 (/usr/local/bin/node)
npm : 6.1.0
OS : macOS High Sierra
Xcode : Xcode 10.0 Build version 10A255
but it still not enough, you should add to config.xml file:




if you have issues with CORS after this modification please let me know and i will advice you how to avoid it

@Stefano1964

This comment was marked as outdated.

Copy link

@Stefano1964 Stefano1964 commented Sep 26, 2018

@Bravo2x you have to edit CDVWKWebViewEngine.m:
ionic-team/cordova-plugin-ionic-webview#176

@booleanbetrayal

This comment was marked as outdated.

Copy link
Author

@booleanbetrayal booleanbetrayal commented Sep 26, 2018

@Stefano1964 - I have a branch with your suggested changes and am NOT seeing any change regarding keyboard displacement. Are you sure we're talking about the same issue? Are you using viewport-fit=cover"?

@Stefano1964

This comment was marked as outdated.

Copy link

@Stefano1964 Stefano1964 commented Sep 26, 2018

Yes, i'm sure, and yes i'm using viewport-fit=cover", for me this solved the issue.

@andrewballester

This comment was marked as outdated.

Copy link

@andrewballester andrewballester commented Oct 10, 2018

This was killing me. We seemed to find an ugly fix that works without taking viewport-fit:cover off.
$('input').on("blur",function (e) {
window.scrollTo(0,0);
});

@AngelaRg

This comment was marked as outdated.

Copy link

@AngelaRg AngelaRg commented Oct 12, 2018

For me the solution was changing the keyboard plugin I was using, from ionic-plugin-keyboard (https://github.com/ionic-team/ionic-plugin-keyboard , which was actually deprecated) to cordova-plugin-ionic-keyboard (https://github.com/ionic-team/cordova-plugin-ionic-keyboard). It now works fine.

@gueno

This comment was marked as outdated.

Copy link

@gueno gueno commented Oct 17, 2018

As @andrewballester suggested it, the ugly fix he found went through my mind (and it hurts..)
But when you have a form with multiple fields and using ios keyboard arrows to navigate between them, the screen jumps to the top and if your field was way below the "fold", it is then hidden behind the keyboard

Another ugly fix to fix the first ugly fix is to use another method :

/**
 * iOS 12 bug for keyboard dismissing, view not restored ಠ_ಠ
 */
if (device.ios && device.osVersion.split('.')[0] >= 12) {
    jQuery(document).delegate('input, textarea', 'blur', function(){
        setTimeout(function(){ 
	    // did not work for me straight away without a small timeout ಠ_ಠ
	    jQuery('html').animate({height: '100.1vh'}, 100, function(){ 
	        // did not work for me with just one instruction with 100vh  ಠ_ಠ
	        // the easing smooth doesn't work all the time properly ಠ_ಠ
		jQuery(this).animate({height: '100vh'}, 1);
	    });
        },100);
    });
}
@amirkaromashkin

This comment has been minimized.

Copy link

@amirkaromashkin amirkaromashkin commented Oct 19, 2018

Experience same without Cordova, using pure WKWebView.
From native code side the following workaround worked: webView.setNeedsLayout() on keyboard dismissal.
UI is re-rendered correctly but instantly, not smoothly like in Safari.

@KhanhPhamDinh

This comment was marked as outdated.

Copy link

@KhanhPhamDinh KhanhPhamDinh commented Oct 24, 2018

Hi all, i am facing that issue run on IOS 12 that was built with Xcode 10 (if you build with XCode 9, the issue don't appear). IOS 12 will automatic change content offset of WKScrollview in WKWebview fit with height of keyboard in case keyboardWillShow, but it didn't revert it in case keyboardWillHide. That is my solution to fixed it, hope it help for you.

/**
 * observer notification when keyboard will hide
 */
[[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillHide)
                                                     name:UIKeyboardWillHideNotification
                                                   object:nil];

/////////////--------------------------//////////////
/*
 *Description: this method was trigger by selector keyboarwillhide from notification
 */
-(void)keyboardWillHide
{
    if (@available(iOS 12.0, *)) {
        WKWebView *webview = (WKWebView*)self.webView;
         for(UIView* v in webview.subviews){
              if([v isKindOfClass:NSClassFromString(@"WKScrollView")]){
                      UIScrollView *scrollView = (UIScrollView*)v;
                      [scrollView setContentOffset:CGPointMake(0, 0)];
              }
          }
     }
}
@booleanbetrayal

This comment was marked as outdated.

Copy link
Author

@booleanbetrayal booleanbetrayal commented Oct 24, 2018

Thanks @KhanhPhamDinh ! I've validated that this is working for me in a fork of the cordova-ionic-webview project, and have submitted a PR crediting you: ionic-team/cordova-plugin-ionic-webview#201

@dpogue

This comment has been minimized.

Copy link
Member

@dpogue dpogue commented Nov 2, 2018

For the record, I strongly suspect the issue was introduced as a side effect in WebKit/webkit@0ff63c4

@booleanbetrayal

This comment has been minimized.

Copy link
Author

@booleanbetrayal booleanbetrayal commented Nov 2, 2018

Thanks for doing some digging @dpogue . I've written the author at Apple, so hopefully there is some visibility internally there, now. 🤞

@tobeee

This comment has been minimized.

Copy link

@tobeee tobeee commented Nov 7, 2018

We found building with Xcode 9 as opposed to 10 reverted any weird keyboard issues (obviously not long term solution)

@c-emil

This comment was marked as outdated.

Copy link

@c-emil c-emil commented Aug 22, 2019

If you want a solution without jQuery that handles all inputs that are not even displayed yet, try this:

    let isFormFieldActive = false;

    window.addEventListener('focusin', function focusInHack() {
      const elementName = document.activeElement.localName;
      if (['select', 'textarea', 'input'].includes(elementName)) {
        isFormFieldActive = true;
      }
    });

    window.addEventListener('focusout', function focusOutHack() {
      if (isFormFieldActive) {
        setTimeout(() => {
          window.scrollTo(0, document.documentElement.clientHeight);
        });
        isFormFieldActive = false;
      }
    });
@dpogue

This comment has been minimized.

Copy link
Member

@dpogue dpogue commented Sep 6, 2019

A fix for this was just merged into WebKit (WebKit/webkit@ec5ad1b) and should be available in the future version of iOS.

Now that I understand the problem, I'm going to see if I can put together a Cordova plugin to replicate the fix on earlier versions.

@dpogue

This comment has been minimized.

Copy link
Member

@dpogue dpogue commented Sep 6, 2019

As a workaround until that fix is released in a future iOS version, I've done my best to backport it to a plugin:
📦 cordova-plugin-wkkeyboardfix: npm / repo

The code is very hacky and is not guaranteed to be safe to submit to the app store. Use at your own risk.

@Bessonov

This comment has been minimized.

Copy link

@Bessonov Bessonov commented Sep 6, 2019

Although it's not relevant for me now, I would say thank you for your effort @dpogue

@MichaelIT

This comment was marked as outdated.

Copy link

@MichaelIT MichaelIT commented Sep 8, 2019

I make a patch for it.https://github.com/MichaelIT/patch-ios12-webview-keyboard

npm add patch-ios12-webview-keyboard --save
import 'patch-ios12-webview-keyboard'
@joacim-boive

This comment has been minimized.

Copy link

@joacim-boive joacim-boive commented Sep 10, 2019

A simple solution I've come up with is to call window.scrollBy(0,0) onBlur of the field in question.
This forces a repaint of the window and solves the problem.

I guess it could be implemented as a plugin, but that's above my current abilities unfortunately. :)

In our case we just updated our React component and that solved it everywhere in our applications.

@lhmarcilli

This comment has been minimized.

Copy link

@lhmarcilli lhmarcilli commented Sep 12, 2019

i have the same problem... xcode 10.1... and all devices... help-me jesus!!!!

@dpogue

This comment has been minimized.

Copy link
Member

@dpogue dpogue commented Sep 12, 2019

@jnordstrom1983

This comment has been minimized.

Copy link

@jnordstrom1983 jnordstrom1983 commented Sep 16, 2019

I had success implementing the solution suggested by @joacim-boive

Simple (yet ugly) solution that worked for me:
$(document).on('blur', 'input', function(){ window.scrollTo(0,0) })

usernuno added a commit to OutSystems/cordova-plugin-inappbrowser that referenced this issue Sep 16, 2019
…tioned

Known WKWebView issue. Only happens in iOS 12 and later.

Issue link in cordova-ios: apache/cordova-ios#417
Original fix patch: kozmanbalint/cordova-plugin-wkwebview-engine@644fc16

Excerpt from the issue link: When an input that would require webview centering is clicked, the viewport is repositioned to center that input, as iOS has traditionally done. However, when dismissing the keyboard, the viewport is not re-positioned properly back to its original position.

Fixes https://outsystemsrd.atlassian.net/browse/RNMT-3293
EiyuuZack added a commit to OutSystems/cordova-plugin-statusbar that referenced this issue Sep 18, 2019
apache/cordova-ios#417 does not apply to WKWebView,
therefore always return NO when running there. This entire workaround to
disable viewport fit injection is to be _removed_ once WKWebView is the
_sole_ option.

References https://outsystemsrd.atlassian.net/browse/RNMT-3245
@ssnielsen

This comment has been minimized.

Copy link

@ssnielsen ssnielsen commented Sep 25, 2019

Experiencing the same for our cordova app for users on iOS 13. Glad to see it'll be fixed in an upcoming iOS version.

Great work with the plugin @dpogue! Have anybody had an app released (i.e. go through app store review) with that?

@dpogue

This comment has been minimized.

Copy link
Member

@dpogue dpogue commented Sep 25, 2019

Have anybody had an app released (i.e. go through app store review) with that?

Yes, 2 of our apps have gone through review and been approved. The plugin tries to hide the fact that it's using internal APIs, so it should pass App Store review, but I feel obligated to mention in the README that there is a slight risk.

@joacim-boive

This comment has been minimized.

Copy link

@joacim-boive joacim-boive commented Sep 27, 2019

I had success implementing the solution suggested by @joacim-boive

Simple (yet ugly) solution that worked for me:
$(document).on('blur', 'input', function(){ window.scrollTo(0,0) })

Great! But scrollTo is not a great solution. For long forms it scrolls to the top of the page on every input change - really bad user behavior.

That's why you should use scrollBy(0,0) instead - as I suggested. ;)
Because this doesn't move the page around - but repaints the page.

@spinninghamster

This comment has been minimized.

Copy link

@spinninghamster spinninghamster commented Sep 30, 2019

I am using XCode 10 and iOS 12.4 and am not experiencing this issue. Is this happening in the simulator too? Or just real devices.

I am using cordova-plugin-wkwebview-engine.

@LautaroLorenz

This comment was marked as off-topic.

@dpogue

This comment was marked as off-topic.

Copy link
Member

@dpogue dpogue commented Oct 25, 2019

related ionic-team/cordova-plugin-ionic-keyboard#99

I don't believe this is related at all.

@michelvermeer

This comment has been minimized.

Copy link

@michelvermeer michelvermeer commented Oct 28, 2019

I'm facing the same issue when using viewport-fit=cover on iOS. It seems the keyboard popping up triggers a window.scroll event while it does not when hiding it.
Since there's no real solution to it yet, here's something I've created to fix the issue.
Note: Your should have a height of 100vh and handle all scrolling behaviour in any of its children.

let timeout;
function blurEvent(e) {
	timeout = setTimeout (() => {
		window.scrollTo(0, 0);
	}, 50);
}
		
function focusEvent(e) {
	clearTimeout (timeout);
}

window.addEventListener('scroll', function(e) {
	let inputfields = document.querySelectorAll('input');
	for (let inp of inputfields) {
		inp.removeEventListener('blur', blurEvent);
		inp.addEventListener('blur', blurEvent);
				
		inp.removeEventListener('focus', focusEvent);
		inp.addEventListener('focus', focusEvent);
	}
});
@Kepro

This comment has been minimized.

Copy link

@Kepro Kepro commented Jan 10, 2020

@dpogue thank you for this fix! we needed to migrate from UIWebView and now we were stuck on this issue, but your fix it's just working! :)

@mattcwebster

This comment has been minimized.

Copy link

@mattcwebster mattcwebster commented Jan 22, 2020

A fix for this was just merged into WebKit (WebKit/webkit@ec5ad1b) and should be available in the future version of iOS.

Now that I understand the problem, I'm going to see if I can put together a Cordova plugin to replicate the fix on earlier versions.

@dpogue do you know when the future version for this fix will be live.

i'm experiencing some very weird functionality with the ios keyboard in my ionic cordova ios app. After the blur event fires from the keyboard it leaves a blank whitespace in viewport that doesn't go away.

@dpogue

This comment has been minimized.

Copy link
Member

@dpogue dpogue commented Jan 23, 2020

@dpogue do you know when the future version for this fix will be live.

i'm experiencing some very weird functionality with the ios keyboard in my ionic cordova ios app. After the blur event fires from the keyboard it leaves a blank whitespace in viewport that doesn't go away.

The fix has been merged, but has not made it into a shipping version of iOS yet. Only Apple knows when it will be pulled in to a shipping version, and they do not comment about future releases.

In the meantime, the same fix is available as a plugin: https://www.npmjs.com/package/cordova-plugin-wkkeyboardfix

@mattcwebster

This comment has been minimized.

Copy link

@mattcwebster mattcwebster commented Jan 23, 2020

@dpogue do you know when the future version for this fix will be live.
i'm experiencing some very weird functionality with the ios keyboard in my ionic cordova ios app. After the blur event fires from the keyboard it leaves a blank whitespace in viewport that doesn't go away.

The fix has been merged, but has not made it into a shipping version of iOS yet. Only Apple knows when it will be pulled in to a shipping version, and they do not comment about future releases.

In the meantime, the same fix is available as a plugin: https://www.npmjs.com/package/cordova-plugin-wkkeyboardfix

@dpogue wow just installed the plugin you mentioned, and it fixed it right away!!! this thing drove me nuts probably wasted 2 days of development trying to figure it out before I just gave up. Thank you!

Also, do you know why apple would possibly reject just for using this package? Im going to roll the dice.

@Kepro

This comment has been minimized.

Copy link

@Kepro Kepro commented Jan 23, 2020

@mattcwebster just read a thread little bit... don't be lazy if you spend 2 days with looking for fix :P

@dpogue

This comment has been minimized.

Copy link
Member

@dpogue dpogue commented Jan 23, 2020

Also, do you know why apple would possibly reject just for using this package? Im going to roll the dice.

@mattcwebster It uses private APIs (albeit obfuscated to pass detection), which is not permitted. Unfortunately using those APIs is necessary to match how WebKit calculates the keyboard sizing/positioning.

@mattcwebster

This comment has been minimized.

Copy link

@mattcwebster mattcwebster commented Jan 23, 2020

Darn, after further testing the package fix noted by @dpogue worked, but intermittently.

What finally worked for me was to:

  1. make sure to have latest Ionic Web View for Cordova
    cordova plugin rm cordova-plugin-ionic-webview
    cordova plugin add cordova-plugin-ionic-webview@latest

  2. install cordova-plugin-ionic-keyboard
    cordova plugin add cordova-plugin-ionic-keyboard --save

these two steps I already had done, but here's what fixed it, add the following preference to your config.xml file

*note, the downfall here is that when focusing on an input, the keyboard will overlap the input, unless input at top of viewport - which can be done. However, this problem is much better than the bug I was dealing with where the keyboard would leave a whitespace in viewport (spanning the height of the keyboard) and not go away.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Apache Cordova: project-bot automatio...
new/unassigned/reopened issues
You can’t perform that action at this time.