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

shrinkView not work on iOS12 #77

Open
ActNotSign opened this issue Sep 20, 2018 · 28 comments
Open

shrinkView not work on iOS12 #77

ActNotSign opened this issue Sep 20, 2018 · 28 comments

Comments

@ActNotSign
Copy link

have solution ?
it's bug ?

@ActNotSign ActNotSign changed the title shrinkView not work in iOS12 shrinkView not work on iOS12 Sep 20, 2018
@Aarbel
Copy link

Aarbel commented Sep 20, 2018

please put screenshots and more detailled issue

@EternallLight
Copy link

EternallLight commented Sep 21, 2018

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.

@Aarbel
Copy link

Aarbel commented Sep 21, 2018

@cjpearson

@mattio
Copy link

mattio commented Sep 28, 2018

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;
    }
}

@ActNotSign
Copy link
Author

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];

@mattio
Copy link

mattio commented Oct 2, 2018

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.

@Birowsky
Copy link

Birowsky commented Oct 2, 2018

Just as another reference, right after tapping the input:

screen shot 2018-10-02 at 21 59 45

@EternallLight did you figure out a workaround by any chance?

@EternallLight
Copy link

@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.

@zspencer
Copy link

zspencer commented Oct 22, 2018

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:

  1. Clone https://github.com/wecohere/cordova-plugin-keyboard
  2. Checkout the zs-fix-keyboard branch
  3. cordova plugin add relative/path/to/the/cloned/cordova-plugin-keyboard
  4. 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.

@jremi
Copy link

jremi commented Oct 26, 2018

@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

@zspencer
Copy link

zspencer commented Oct 26, 2018

@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.

@jremi
Copy link

jremi commented Oct 26, 2018

@zspencer i am actually not using ionic with my cordova app. I am using cordova + framework7. Good to know. Thanks for info

@zspencer
Copy link

To clarify, I am also not using ionic, the cordova-plugin-ionic-webview provides a solid WKWebView implementation for non-ionic apps.

@jremi
Copy link

jremi commented Oct 26, 2018

ah good you said that. Maybe i will drop these in then.

@startupfoundry
Copy link

  1. 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!

@edvenkat
Copy link

@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 .

Crash-- added a commit to cozy/cordova-plugin-keyboard that referenced this issue Nov 22, 2018
@mallociFrancesca
Copy link

mallociFrancesca commented Dec 7, 2018

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

@zspencer
Copy link

zspencer commented Dec 8, 2018

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.

@edvenkat
Copy link

edvenkat commented Jan 10, 2019

@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

@zspencer
Copy link

The solution remains to switch off the built in browser an onto the ionic maintained webview and keyboard plugins, per this comment -
#77 (comment)

@dizzlr
Copy link

dizzlr commented Jan 27, 2019

@zspencer i not good in objective-c how can i switch the plugin on or off with paramter ??

@zspencer
Copy link

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.

@dizzlr
Copy link

dizzlr commented Jan 27, 2019

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

@zspencer
Copy link

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!

@brianespinosa
Copy link

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.

@AdrianoGeraldeli
Copy link

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:

  1. Clone https://github.com/wecohere/cordova-plugin-keyboard
  2. Checkout the zs-fix-keyboard branch
  3. cordova plugin add relative/path/to/the/cloned/cordova-plugin-keyboard
  4. 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

@zspencer
Copy link

@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]

@Constaline
Copy link

Using this command can add the plugin easily

cordova plugin add https://github.com/wecohere/cordova-plugin-keyboard#zs-fix-keyboard --nofetch 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests