ionic-team / capacitor

Build cross-platform Native Progressive Web Apps for iOS, Android, and the Web ⚡️
https://capacitorjs.com
MIT License
11.31k stars 962 forks source link

iOS 12 App Touch-Areas are offset after keyboard is hidden #814

Closed ghost closed 5 years ago

ghost commented 5 years ago

Steps to reproduce:

What happens: -> The UI shifts down, but touchareas of UI-Elements are still offset. Causing always touching the wrong button

Tested with iPhone X and iPhone 8 Simulator on iOS 11 and iOS 12. Only happens on iOS 12 (both Simulators)

When you take a look at the View Hierarchy it seems, some Subviews of the WebView are still offset. Screenshot of Hierarchy attached.

bildschirmfoto 2018-09-21 um 18 29 11

jcesarmobile commented 5 years ago

Are you using Xcode 10, right? I think this is a bug in the SDK 12 included in Xcode 10.

Can you try with Xcode 9 and see if you can reproduce there?

But testing directly from Xcode 9 in iOS 12 devices is not possible as it fails to install, you'll have to export the ipa and install it manually

ghost commented 5 years ago

You are right, does not happen with Xcode 9 / iOS 11. But when you open an URL and load a website in a WKWebView everything works fine with iOS 12. So it seems there is an issue in the Capacitor-Layer.

jcesarmobile commented 5 years ago

I meant, can you test this in Xcode 9 but on iOS 12 device?

ghost commented 5 years ago

Just tried it, built with Xcode 9 and run on iOS 12 device works fine.

luke-rogers commented 5 years ago

I am also seeing this issue when using keyboard which causes input to scroll into view (may be through using keyboard arrows) then closing the keyboard, the buttons in my toolbar cannot be clicked. When you press them nothing happens. This issue is consistently reproducible and makes the app unusable.

Inline with this issue, it does not seem to affect my app when running on iOS 11.

Not super sure the cause of this issue, many issues have been raised across other projects, but it is also effecting capacitor apps. ionic-team/cordova-plugin-ionic-webview#176 apache/cordova-ios#417 http://www.openradar.me/44655885

Potential test project https://github.com/dpogue/WKScrollTest

nikmartin commented 5 years ago

We just filed the same bug against ionic 4, but was told it was probably a capacitor issue as far as ionic is concerned, so rather than open another issue, I'll paste it here:

Ionic Info Run ionic info from a terminal/cmd prompt and paste the output below.

ionic (Ionic CLI)          : 4.1.0 (/usr/local/lib/node_modules/ionic)
   Ionic Framework            : @ionic/angular 4.0.0-beta.7
   @angular-devkit/core       : 0.7.5
   @angular-devkit/schematics : 0.7.5
   @angular/cli               : 6.1.5
   @ionic/ng-toolkit          : 1.0.8
   @ionic/schematics-angular  : 1.0.6

System:

   NodeJS : v8.11.4 (/usr/local/bin/node)
   npm    : 5.6.0
   OS     : macOS High Sierra

Describe the Bug When the on screen keyboard is displayed and hidden (from a footer input), it causes the UI to be scrolled up, the user interface is 'shifted' up by the width of the keyboard. When the keyboard then disappears, all the UI input is still shifted up by the width of the keyboard. This means all clicks in the UI are too high (ie inputs, etc). Also, when an input is in the content area, the keyboard will hide the input instead of scrolling it as it should.

Steps to Reproduce Steps to reproduce the behavior:

  1. Clone: https://github.com/grabitlogistics/ios12kbd
  2. run npm i && ng build && npx cap add ios && npx cap copy ios && npx cap open ios
  3. build and run the app on an ios 12 device
  4. Click in an upper input to display the keyboard, then click outside to hide the keyboard and lose focus.
  5. Click on an input in the footer, making the keyboard appear and shift the inputs up. Click outside the input to hide the keyboard.
  6. All touch events have now been shifted up by the height of the keyboard, so to click in the input in the content OR the footer, you must click a few inches above the respective input (about the height of the keyboard)

Related Code sample test case: https://github.com/grabitlogistics/ios12kbd

Additional Context This ONLY happens on iOS 12, on a hardware device OR emulator. To test in an emulator, you must use the emulated keyboard in order to cause the UI to shift up.

hghammoud commented 5 years ago

I did some testing on multiple ios/emulators XCode 10.0

iPhone 8 Plus iOS 11 -> no view shits everything is ok iPhone 8 Plus iOS 12 -> no view shits everything is ok IPhone X iOS 11.3 -> view shits but clicks are in place () IPhone X ans XS iOS 12 -> view shits and clicks are not accurate (the click action triggers lower the the touch point - same amount of view shit)

it seems related seems related to the extra track pad. image

YodaVN commented 5 years ago

Anyone has the fix of this problem?

sbannigan commented 5 years ago

Can confirm that this issue exists in Cordova on iOS 12 as well https://github.com/apache/cordova-ios/issues/417

KhanhPhamDinh commented 5 years ago

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). The root cause of issue is WKScrollview in WKWebview will be changed automatically content offset fit with height of keyboard in case keyboard is showed, but it didn't reset in case keyboard is hidden. 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)];
             }
          }
     }
}
JacoRoos commented 5 years ago

@jcesarmobile Regarding this comment: https://github.com/ionic-team/capacitor/issues/814#issuecomment-423609753

Is it not possible to set the SDK that XCode uses to build instead of having to install another version of XCode?

jcesarmobile commented 5 years ago

Here it says you can but it present a few problems https://stackoverflow.com/questions/44985307/xcode-9-how-to-install-ios-10-sdk

JacoRoos commented 5 years ago

OK, thanks for the feedback! Looks like it would be more of a headache to do this than installing an additional version of XCode.

sarapoll commented 5 years ago

any solution?

hghammoud commented 5 years ago

This was merged in corodva ionic webview https://github.com/ionic-team/cordova-plugin-ionic-webview/commit/a67056816ee7fd2b8c74eef1854f2effbd145aea

Anyone knows how to integrate it with capacitor (I am not using cordova plugin)?

oliverandersencox commented 5 years ago

this is exactly the problem I am having - any use of the keyboard completely messes up the webview container and shifts it all up

oliverandersencox commented 5 years ago

this happens on the IOS device itself and has completely halted any chances of pushing out to customers

oliverandersencox commented 5 years ago

not sure if this is related however, my app will also always load first time with a slight gap under the app displaying the WKScrollView:

screenshot 2018-11-21 at 18 20 01 screenshot 2018-11-21 at 18 34 38

If I rerun the app it will sometime disappear, other times it wont - very sporadic

snapeuh commented 5 years ago

Hello, we are experiencing the same bug on iOS 12. When the keyboard closes, the webview keeps a "padding" from the bottom like if the keyboard was still visible.

moberwasserlechner commented 5 years ago

Same here. But only after I upgraded to beta.11.

On every view I use the keyboard the whole app is shifts up and stays there until I rotate my phone to landscape and back.

Tabbed email input field with keyboard displayed. img_3354 Keyboard loses focus and disappears but view stays shifted up. img_3355

This is a blocker for all apps using the keyboard.

I experience the problem with XCode 10 and XCode 10.1 deployment target was 11.0.

moberwasserlechner commented 5 years ago

I adapted the solution from https://github.com/ionic-team/capacitor/issues/814#issuecomment-432724789 to Swift and used it in the ios/App/App/AppDelegate.swift.

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

    return true
  }

    @objc func keyboardWillHide(notification: NSNotification) {
        if #available(iOS 12.0, *) {
            let vc = self.window?.rootViewController as! CAPBridgeViewController
            for v in vc.bridgedWebView!.subviews {
                if v is UIScrollView {
                    let scrollView = v as! UIScrollView
                    scrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
                }
            }
        }
    }

This fixes my issues.

dabaaaz commented 5 years ago

That last solution works fine ! But I got a problem when I released. The AppDelegate.swift file is not taking into consideration, because of an optimization level during the release build.

That problem can be fixed by disabling the release optimizations : In Xcode and "Build Settings", seek "optimization level" and select "None [-O0]".

rj33 commented 5 years ago

As well as the keyboard input issues, I appear to be having essentially the same problem with the UI that pops up to handle selection of choices in a form select element.

pixelbucket-dev commented 5 years ago

I had the same issue. My fix was to add the following code to the index.html:

    window.addEventListener('keyboardWillHide', () => {
        window.scrollTo(0,0);
    document.body.scrollTop = 0;
    });
nicdichiara commented 5 years ago

I had the same issue. My fix was to add the following code to the index.html:

    window.addEventListener('keyboardWillHide', () => {
        window.scrollTo(0,0);
  document.body.scrollTop = 0;
    });

Can confirm this works as a workaround, even if you update xcode to 10.1. Thank you @Nudelsieb !!

vuthanhict commented 5 years ago

 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

christophersansone commented 5 years ago

FWIW, I implemented @Nudelsieb's solution above, with a couple caveats.

  1. It requires cordova-plugin-keyboard for the keyboardWillHide event to trigger.

  2. When immediately transitioning from one input to another, the keyboardWillHide event will trigger, even though the keyboard does not actually have time to hide. That seemed to cause undesired scrolling. I added a setTimeout() to prevent it from executing immediately, which helped.

const scrollToTopFn = () => {
  if (window.Keyboard && !window.Keyboard.isVisible) {
    window.scrollTo(0,0);
    window.document.body.scrollTop = 0;
  }
};

window.addEventListener('keyboardDidHide', () => {
  window.setTimeout(scrollToTopFn, 100);
});
thestevenmellor commented 5 years ago

Finally got it to work.. I had to piece together this file here: fix keyboard displacement bug in iOS 12 WKWebView from @hghammoud

A straight copy didn't work, but taking each part and adding it to my CDVWKWebViewEngine.m file worked for me. I'll post my file if anyone needs it.

Here's my setup: Ionic: ionic (Ionic CLI) : 4.6.0 Ionic Framework : ionic-angular 3.9.2 @ionic/app-scripts : 3.1.10

Cordova: cordova (Cordova CLI) : 8.1.2 (cordova-lib@8.1.1) Cordova Platforms : android 7.1.4, ios 4.5.5 Cordova Plugins : cordova-plugin-ionic-keyboard 2.1.3, cordova-plugin-ionic-webview 1.1.1, (and 18 other plugins)

System: ios-deploy : 1.9.2 NodeJS : v6.15.1 (/usr/local/Cellar/node/11.5.0/bin/node) npm : 3.10.10 OS : macOS Mojave Xcode : Xcode 10.1 Build version 10B61

zenochan commented 5 years ago
  1. template

    <input  (blur)="scrollToTop()">
  2. page

    scrollToTop()
    {
    window.scrollTo(0,0);
    }
  3. down

sooheesh commented 5 years ago

https://github.com/ionic-team/cordova-plugin-ionic-webview/issues/176#issuecomment-455032360

this worked.

longbo666 commented 5 years ago

期待有人能真正解决

daniellizik commented 5 years ago

You are right, does not happen with Xcode 9 / iOS 11. But when you open an URL and load a website in a WKWebView everything works fine with iOS 12. So it seems there is an issue in the Capacitor-Layer.

I can still reproduce this with iOS 11.4.1 and xcode 9.4.1

jcesarmobile commented 5 years ago

I think this should be fixed in next release, I made a few keyboard changes that combined seem to fix it.

@daniellizik what you comment should be a different issue as this only affects iOS 12 when using Xcode 10, not iOS 11 despite the Xcode version, and doesn't affect any iOS version when using Xcode 9.

alphagamer7 commented 5 years ago

@jcesarmobile Confirming that even with the latest release (4.0.2) the issue is not fixed.

jcesarmobile commented 5 years ago

Not sure what 4.0.2 you mean, but I’m talking about next capacitor release (1.0.0 beta 18, still not released)

MarcAndreC commented 5 years ago

@jcesarmobile Is the fix that you've made is in a branch that we can test?

jcesarmobile commented 5 years ago

Beta 18 is out, can you test with it?

solojuve1897 commented 5 years ago

@jcesarmobile Part of this bug is fixed but there is still strange behaviour. Check my video:

https://drive.google.com/file/d/11Msg2lSiW1UoN-si6nL1QxLS93shBu9h/view

None of these occur on my Android-devices.

calvinckho commented 5 years ago

@jcesarmobile it is working great on my iPhone 7 test device running iOS 12! It seems to have completely fixed the bug introduced by Apple's webview in iOS 12. Thanks for this update.

davidrinnan commented 5 years ago

when the given page loads, if it is ios etc etc, I attach a listener document.addEventListener('focusout', resetScroll);

reset scroll is running on a short timeout and checks if the innerheight and height is the same, if se, it resets the scroll. This results in the scroll only being reset once the keyboard is removed from screen, rather than everytime the focus is changed.

 setTimeout(()=>{
        if (window.innerHeight == screen.height) {
            window.scrollTo(0, 0)    
        }
    },timeout);
jcesarmobile commented 5 years ago

I can't reproduce since beta 18 and calvinckho also confirmed that it's working fine for him, so I'm going to close. For other strange behaviours report new issues.