cordova-plugin-keyboard
cordova-plugin-keyboard copied to clipboard
shrinkView not work on iOS12
have solution ? it's bug ?
please put screenshots and more detailled issue
Hello,
I have the same issue after upgrading to iOS 12. When I click on a textarea, and keyboard shows up, it takes the HTML contents of the page "too high". There is also a new vertical scrollbar, which I can use to bring the contents back to its normal place - right above the keyboard. I can also pull it back atop again if I swipe up on non-scrollable area of my application.
Here are the screenshots how it looks like: https://www.screencast.com/t/DpbAwwOmhBO - initially after opening the keyboard https://www.screencast.com/t/7D9Fapjel8 - scrolled down a bit And from native perspective: https://www.screencast.com/t/mHI6ZIyRZ
UPD. If I set Keyboard.disableScrollingInShrinkView(true), the vertical scrolling is not longer available, so that the visible HTML is always stuck at the top.
Please, take a look at this. In the meanwhile, I will try to find my way around on my own and find a fix.
Thanks, Andrey.
@cjpearson
I was poking around -shrinkViewKeyboardWillChangeFrame: to see what the before and after sizes were when I noticed self.webView.scrollView.contentSize
was still incorrect at the end on iOS 12 only -- it was fine on iOS 11.
I'm sure there's a better way, but this is how I'm hacking my way around the problem until the maintainers have a chance to take a look for a real solution. The new bits are the two checks for iOS 12.
Full file: https://gist.github.com/mattio/ba5d77474e725463bc75cfbf1dba0cca
- (void)shrinkViewKeyboardWillChangeFrame:(NSNotification*)notif
{
// No-op on iOS 7.0. It already resizes webview by default, and this plugin is causing layout issues
// with fixed position elements. We possibly should attempt to implement shrinkview = false on iOS7.0.
// iOS 7.1+ behave the same way as iOS 6
if (NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_7_1 && NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
return;
}
// If the view is not visible, we should do nothing. E.g. if the inappbrowser is open.
if (!(self.viewController.isViewLoaded && self.viewController.view.window)) {
return;
}
self.webView.scrollView.scrollEnabled = YES;
CGRect screen = [[UIScreen mainScreen] bounds];
CGRect statusBar = [[UIApplication sharedApplication] statusBarFrame];
CGRect keyboard = ((NSValue*)notif.userInfo[@"UIKeyboardFrameEndUserInfoKey"]).CGRectValue;
// Work within the webview's coordinate system
keyboard = [self.webView convertRect:keyboard fromView:nil];
statusBar = [self.webView convertRect:statusBar fromView:nil];
screen = [self.webView convertRect:screen fromView:nil];
// if the webview is below the status bar, offset and shrink its frame
if ([self settingForKey:@"StatusBarOverlaysWebView"] != nil && ![[self settingForKey:@"StatusBarOverlaysWebView"] boolValue]) {
CGRect full, remainder;
CGRectDivide(screen, &remainder, &full, statusBar.size.height, CGRectMinYEdge);
screen = full;
}
// Get the intersection of the keyboard and screen and move the webview above it
// Note: we check for _shrinkView at this point instead of the beginning of the method to handle
// the case where the user disabled shrinkView while the keyboard is showing.
// The webview should always be able to return to full size
CGRect keyboardIntersection = CGRectIntersection(screen, keyboard);
if (CGRectContainsRect(screen, keyboardIntersection) && !CGRectIsEmpty(keyboardIntersection) && _shrinkView && self.keyboardIsVisible) {
// I'm sure there's a better way...
if (@available(iOS 12, *)) {
self.webView.scrollView.scrollEnabled = !self.disableScrollingInShrinkView; // Order intentionally swapped.
screen.size.height -= keyboardIntersection.size.height;
CGSize revisedSize = CGSizeMake(self.webView.scrollView.frame.size.width, self.webView.scrollView.frame.size.height - keyboard.size.height);
self.webView.scrollView.contentSize = revisedSize;
}
else {
screen.size.height -= keyboardIntersection.size.height;
self.webView.scrollView.scrollEnabled = !self.disableScrollingInShrinkView;
}
}
// A view's frame is in its superview's coordinate system so we need to convert again
self.webView.frame = [self.webView.superview convertRect:screen fromView:self.webView];
// I'm sure there's a better way...
if (@available(iOS 12, *)) {
CGSize revisedSize = CGSizeMake(self.webView.frame.size.width, self.webView.frame.size.height - keyboard.size.height);
self.webView.scrollView.contentSize = revisedSize;
}
}
I was poking around -shrinkViewKeyboardWillChangeFrame: to see what the before and after sizes were when I noticed
self.webView.scrollView.contentSize
was still incorrect at the end on iOS 12 only -- it was fine on iOS 11.I'm sure there's a better way, but this is how I'm hacking my way around the problem until the maintainers have a chance to take a look for a real solution. The new bits are the two checks for iOS 12.
Full file: https://gist.github.com/mattio/ba5d77474e725463bc75cfbf1dba0cca
- (void)shrinkViewKeyboardWillChangeFrame:(NSNotification*)notif { // No-op on iOS 7.0. It already resizes webview by default, and this plugin is causing layout issues // with fixed position elements. We possibly should attempt to implement shrinkview = false on iOS7.0. // iOS 7.1+ behave the same way as iOS 6 if (NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_7_1 && NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { return; } // If the view is not visible, we should do nothing. E.g. if the inappbrowser is open. if (!(self.viewController.isViewLoaded && self.viewController.view.window)) { return; } self.webView.scrollView.scrollEnabled = YES; CGRect screen = [[UIScreen mainScreen] bounds]; CGRect statusBar = [[UIApplication sharedApplication] statusBarFrame]; CGRect keyboard = ((NSValue*)notif.userInfo[@"UIKeyboardFrameEndUserInfoKey"]).CGRectValue; // Work within the webview's coordinate system keyboard = [self.webView convertRect:keyboard fromView:nil]; statusBar = [self.webView convertRect:statusBar fromView:nil]; screen = [self.webView convertRect:screen fromView:nil]; // if the webview is below the status bar, offset and shrink its frame if ([self settingForKey:@"StatusBarOverlaysWebView"] != nil && ![[self settingForKey:@"StatusBarOverlaysWebView"] boolValue]) { CGRect full, remainder; CGRectDivide(screen, &remainder, &full, statusBar.size.height, CGRectMinYEdge); screen = full; } // Get the intersection of the keyboard and screen and move the webview above it // Note: we check for _shrinkView at this point instead of the beginning of the method to handle // the case where the user disabled shrinkView while the keyboard is showing. // The webview should always be able to return to full size CGRect keyboardIntersection = CGRectIntersection(screen, keyboard); if (CGRectContainsRect(screen, keyboardIntersection) && !CGRectIsEmpty(keyboardIntersection) && _shrinkView && self.keyboardIsVisible) { // I'm sure there's a better way... if (@available(iOS 12, *)) { self.webView.scrollView.scrollEnabled = !self.disableScrollingInShrinkView; // Order intentionally swapped. screen.size.height -= keyboardIntersection.size.height; CGSize revisedSize = CGSizeMake(self.webView.scrollView.frame.size.width, self.webView.scrollView.frame.size.height - keyboard.size.height); self.webView.scrollView.contentSize = revisedSize; } else { screen.size.height -= keyboardIntersection.size.height; self.webView.scrollView.scrollEnabled = !self.disableScrollingInShrinkView; } } // A view's frame is in its superview's coordinate system so we need to convert again self.webView.frame = [self.webView.superview convertRect:screen fromView:self.webView]; // I'm sure there's a better way... if (@available(iOS 12, *)) { CGSize revisedSize = CGSizeMake(self.webView.frame.size.width, self.webView.frame.size.height - keyboard.size.height); self.webView.scrollView.contentSize = revisedSize; } }
like this ?
CGRect keyboardIntersection = CGRectIntersection(screen, keyboard); if (CGRectContainsRect(screen, keyboardIntersection) && !CGRectIsEmpty(keyboardIntersection) && _shrinkView && self.keyboardIsVisible) { if (@available(iOS 12, *)) { CGSize revisedSize = CGSizeMake(self.webView.frame.size.width, screen.size.height); self.webView.scrollView.contentSize = revisedSize; } screen.size.height -= keyboardIntersection.size.height; self.webView.scrollView.scrollEnabled = !self.disableScrollingInShrinkView; } // A view's frame is in its superview's coordinate system so we need to convert again self.webView.frame = [self.webView.superview convertRect:screen fromView:self.webView];
I would replace the entire shrinkViewKeyboardWillChangeFrame:
method with what I have above and see if it solves your problem. It worked for me, but your situation might be different. Keep in mind that, depending on your build process, your manual edits might get overwritten and you may need to make them each time.
Just as another reference, right after tapping the input:

@EternallLight did you figure out a workaround by any chance?
@Birowsky oh, it seems like you're having the same problem... I've been fighting with this for a few days and ended up using WkWebView instead of UIWebView - cordova-plugin-wkwebview-engine or cordova-plugin-ionic-webview. However, it broke all http requests (the CORS issue) and displaying images from cdvfile:// URL (hello, imagecache.js). To fix HTTP requests, I used cordova-plugin-wkwebview-file-xhr - had to manually remove cordova-plugin-wkwebview-engine from its dependencies in config.xml; for cdvfile - ended up with hacking imagecache.js. But, cordova-plugin-wkwebview-file-xhr caused another issues with angular-file-upload that keeps the native FormData under the closure before it is replaced with a the cordova-plugin-wkwebview-file-xhr FormData polyfill. The good part - there are no issues with keyboard at all :) You know what else is strange? Today, I installed our production app from the AppStore, which is supposed to be broken - and it works perfectly! No idea what important I could have changed since then. It seems like WkWebView has some performance benefits, so hope it all was not in vein.
Hello Friends!
I've taken @mattio's lovely patch, and applied it into a branch. I am not planning to release the branch to npm, so here is a quick start for how to use the patch without needign to fork on your own:
- Clone https://github.com/wecohere/cordova-plugin-keyboard
- Checkout the
zs-fix-keyboard
branch -
cordova plugin add relative/path/to/the/cloned/cordova-plugin-keyboard
-
cordova build
It's not perfect, but it will get things by until the maintainer choose to merge or implements a better version.
If you need it in CI, I don't know how to help with that since I do my builds locally :/. Sorry! Maybe someone with more wisdom than I can help with that.
@zspencer thank you for this fix. It resolved the problem for me. Hopefully they soon get that patch into the public npm. I had the tires spinning and going nowhere. This patch got the car out of the sludge. Appreciation x 1000
@jremi - Unfortunately, the patched version seems to be hit-or-miss across devices and iOS versions. The alternative I wound up finally going with is adding both cordova-plugin-ionic-webview
and cordova-plugin-ionic-keyboard
to the project.
This, so far, has provided the smoothest user experience for keyboards appearing and disappearing in my cordova app, but did have a minor bump in the road: The README for cordova-plugin-ionic-webview
tells you to set the WKPort
value. However that resulted in the app launching safari every time the app started. I set it back to the default and everything worked and I have something close to keyboard bliss.
For future reference, here are the relevant snippets of my config.xml
, which are not that exciting and probably not that useful:
<plugin name="cordova-plugin-ionic-webview" spec="^2.2.0">
<variable name="ANDROID_SUPPORT_ANNOTATIONS_VERSION" value="27.+" />
</plugin>
<preference name="WKPort" value="8080" />
<plugin name="cordova-plugin-ionic-keyboard" spec="2.1.3" />
My understanding is that the bug lies in iOS 12 UIWebViews, which are deprecated by Apple; so moving off of UIWebView to WKWebViews, either via the Cordova maintained wkwebview-engine or cordova-plugin-ionic-webview
is likely to provide most consistent maintenance experience moving forward.
@zspencer i am actually not using ionic with my cordova app. I am using cordova + framework7. Good to know. Thanks for info
To clarify, I am also not using ionic, the cordova-plugin-ionic-webview provides a solid WKWebView implementation for non-ionic apps.
ah good you said that. Maybe i will drop these in then.
- https://github.com/wecohere/cordova-plugin-keyboard
@zspencer THANK YOU! Your fork was a massive help for me. There are still some rough edges that the ionic team needs to address with a proper fix but this got my app into a usable state. Much appreciated!
@zspencer i am actually not using ionic with my cordova app. I am using cordova + framework7. Good to know. Thanks for info
we are also facing the same issue. can you please let me know how to fix the issue .
Hi, How did you solved the issue? @cjpearson The patch of @mattio didn't solved the issues for me and also if I install the cordova-plugin-wkwebview-engine the app don't run.. I have the same problem the @Birowsky 's screenshot
Hey @edvenkat and @mallociFrancesca - I don't know that I can help shed much more light on this, other than to say that using cordova-plugin-ionic-webview is not a drop-in replacement; and may require you to adjust your config.xml and/or software design in order for it to work correctly.
I'm more than happy to set up a paid remote pairing session where we step through your code and get it working. Feel free to reach out via any of the means I've listed on my website.
@mattio and @zspencer currently i am using ur branch but i am facing the below issue (refer below link) above 12.0 can you please tell the solution for this?
for your reference https://camo.githubusercontent.com/e19923ed896d8232238d4714c04243f27f386437/687474703a2f2f692e696d6775722e636f6d2f514458307457512e676966
The solution remains to switch off the built in browser an onto the ionic maintained webview and keyboard plugins, per this comment - https://github.com/cjpearson/cordova-plugin-keyboard/issues/77#issuecomment-43346755
@zspencer i not good in objective-c how can i switch the plugin on or off with paramter ??
Sadly, the README for cordova-plugin-ionic-webview does not include installation instructions, but I believe it is because they expect users to know how to use [cordova plugin add](https://cordova.apache.org/docs/en/latest/reference/cordova-cli/#cordova-plugin-command)
I would recommend also running cordova plugin rm cordova-plugin-keyboard
and cordova clean
(or do a cordova platform rm ios
and cordova platform rm android
to ensure you don't have leftover copies of this particular plugin anymore.
thanks @zspencer but i looking for way or function on your branch that stop the cordova keyboard plugin and make it work with parameter because the plugin working fine in some views and some views make trouble so i want way to fire and stop it 😊 thanks in advance
That is the reason why I abandoned trying to make this plugin work and just used the ionic one. The ionic webview works in every single case, whereas this plugin works in most but not all cases; and trying to manage those cases was going to be a nightmare.
It took me about 2 hours to get ionic-webview set up; I strongly encourage you to take the time to investigate it for yourself. You can keep going down the rabbit hole of trying to make this plugin work for your situation, but it's unlikely to be fruitful.
But maybe it will be and I'll learn something!
This same issue is also present on iOS 13. :/
The Ionic flavor of this plugin is also broken for this same feature despite having more activity than this plugin.
Hello Friends!
I've taken @mattio's lovely patch, and applied it into a branch. I am not planning to release the branch to npm, so here is a quick start for how to use the patch without needign to fork on your own:
- Clone https://github.com/wecohere/cordova-plugin-keyboard
- Checkout the
zs-fix-keyboard
branchcordova plugin add relative/path/to/the/cloned/cordova-plugin-keyboard
cordova build
It's not perfect, but it will get things by until the maintainer choose to merge or implements a better version.
If you need it in CI, I don't know how to help with that since I do my builds locally :/. Sorry! Maybe someone with more wisdom than I can help with that.
your solution is perfect .. can you make it public? because I use the phonegap build
@AdrianoGeraldeli - it is public, but you'll have to do the gitwizardry yourself :). I am not really bought into the cordova ecosystem enough to take on maintenance of a public project within it.
I'm happy to do paid pairing sessions to help people solve this problem, just send me an email? [email protected]
Using this command can add the plugin easily
cordova plugin add https://github.com/wecohere/cordova-plugin-keyboard#zs-fix-keyboard --nofetch