ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.02k stars 13.52k forks source link

bug: Keyboard on IOS9 issues #4645

Closed dedib closed 8 years ago

dedib commented 8 years ago

Type: bug

Platform: ios 8 webview

Its related to IOS9

After updating my ios version to IOS 9,on input focus, the whole page flicker, gets pushed down then pulled up.. and a white background shows then disappears after the page gets pulled up.

mhartington commented 8 years ago

Please provide the output from ionic info and ionic platform ls

dedib commented 8 years ago

Ionic info output:

Your system information:

Cordova CLI: 5.4.0 Ionic Version: 1.1.1 Ionic CLI Version: 1.7.10 Ionic App Lib Version: 0.6.5 OS: Node Version: v4.2.2

Ionic platform ls output ionic platform ls Updated the hooks directory to have execute permissions Installed platforms: android 4.1.1, ios 3.9.2 Available platforms: amazon-fireos, blackberry10, browser, firefoxos, webos, windows, windows8, wp8

tlancina commented 8 years ago

Do you have cordova.plugins.Keyboard.disableScroll(true)? Example: https://github.com/driftyco/ionic-starter-tabs/blob/master/js/app.js#L16

zanemcca commented 8 years ago

I am having this same issue I think. It is hard to say exactly what is happening but I know exactly how to reproduce it.

Here is a codepen that should help with recreation. The required parts to cause the issue:

Run this on a new iOS device and when you click in the input box the background should go white. I was able to make it stop by disabling these lines.

FYI @tlancina this is with disableScroll(true);. Any ideas?

zanemcca commented 8 years ago

I should note that this also happens on the simulator for iPhone 6

SebastianSchirmer commented 8 years ago

We are also experiencing this issue, though not only on new devices but also on an iPhone 4s running on iOS 9.1

We spent hours already in analyzing it but couldn't solve it yet. Assumption is that it is somehow related to the scroll container having the overflow-y property set to "scroll". Currently I am experimenting with toggling the overflow-y property using a directive like this:

.directive('qyOverflowScrollToggle', qyOverflowScrollToggle)
    /* @ngInject */
    function qyOverflowScrollToggle($ionicPlatform, $timeout) {
        return {
            restrict: 'A',
            link: link
        };

        function link(scope, element, attrs) {
            $ionicPlatform.ready(function () {
                window.addEventListener('native.keyboardshow', function () {
                    element.css('overflow-y', 'hidden');
                    $timeout(function() {
                        element.css('overflow-y', 'scroll');
                    }, 300);
                });
            });
        }
    }

The directive sets overflow-y to "hidden" when the keyboard is opening up and to "scroll" again after a timeout of 300ms. However, right now this is just one attempt in finding the cause of this issue.

If anyone has anything to add, I'd be really glad as this is basically making our chat application unusable.

khagesh commented 8 years ago

We are also having the same issue on ion-content goes blank and it appears again once we start scrolling. We also have the exact same setup as @zanemcca is using.

carlosbaraza commented 8 years ago

:+1: Same issue here

carlosbaraza commented 8 years ago

I have been researching a bit about the issue. If you are experimenting the same issue than me, what I have discovered is that the white screen is due to an invalidation of the styles. It is very strange because it happens just immediately after click in the iOS "DONE" to close the keyboard, before any Ionic stuff is executed.

screen shot 2015-12-14 at 1 51 52 am

This is how it should look like:

screen shot 2015-12-14 at 2 08 36 am

My guess is:

  1. Cordova/OS/Safari/Something lower than Ionic fires the invalidation of the styles. Then the screen becomes white.
  2. Ionic do its things moving scroll, etc. Then I noticed that if the content is in the top of the screen, so there is no content in the area of the keyboard, the elements' styles will not be recomputed, leaving them white. If the content is bigger than the screen, so it has some scroll, it always works for me.

Hopefully this will help find the issue to someone that has better knowledge on the DOM rendering topic. I spent quite a few time debugging this thing.

chelzwa commented 8 years ago

We're seeing the same issue (or at least the same one as @carlosbaraza). As long as we have enough list items that the page content is larger than the screen, everything works fine, but if there are few enough list items that the ion-list is smaller than the screen, the page content (but not the header) disappears when the keyboard closes.

The content is clearly still there and hidden, because you can click on buttons that you can't see and they work as expected. If you navigate to a new page, the page content reappears as it slides off-screen. Clicking on the input again does not cause anything to reappear, though the keyboard does show and you get a cursor and can change the input. Clicking a button which causes a popup to show also makes all of the content reappear.

Ionic info output: Cordova CLI: 5.4.1 Gulp version: CLI version 3.9.0 Gulp local: Local version 3.8.11 Ionic Version: 1.1.0 Ionic CLI Version: 1.7.8 Ionic App Lib Version: 0.6.4 ios-deploy version: Not installed ios-sim version: 5.0.3 OS: Mac OS X El Capitan Node Version: v0.12.7 Xcode version: Xcode 7.2 Build version 7C68

Ionic platform ls output: Installed platforms: ios 3.9.2 Available platforms: amazon-fireos, android, blackberry10, browser, firefoxos, osx, webos

This forum post also looks like people having the same or related issues: https://forum.ionicframework.com/t/keyboard-closing-causes-entire-page-to-disappear/37284

SebastianSchirmer commented 8 years ago

As mentioned above, we are also experiencing this issue, though not only on new devices but also on an iPhone 4s running on iOS 9.1. On iOS 8, it generally does not occur but we can force it to occur by commenting out 2 lines in ionic.js:

1) https://github.com/driftyco/ionic/blob/master/release/js/ionic.js#L4071:

document.body.classList.remove(KEYBOARD_OPEN_CSS);

2) https://github.com/driftyco/ionic/blob/master/release/js/ionic.js#L4131:

document.body.classList.add(KEYBOARD_OPEN_CSS);

Why is that? It seems that adding and removing the 'keyboard-open' class to the body tag causes a reflow/repaint which "buries" or "hides" the underlying issue.

If I comment out above 2 lines of code, it shouldn't have any impact. However, it does have! When opening / closing the keyboard on a screen having more content than the ion-contents' height, everything is fine. However, if ion-content contains just enough content that the keyboard overlaps it when opened, the content is hidden and we get a white (or whatever bg-color you have) screen where the content actually sits. It has something to do with the overflow-y property having a value of hidden or scroll. If the scroller div has overflow-y set to scroll, this issue occurs. If set to hidden, the issue does not occur.

We have implemented a workaround that sets overflow-y to hidden whenever a keyboard open or close transition happens. After the open/close transition has finished, we set overflow-y back to scroll. It works. However, if content in ion-content is not enough to scroll, we leave overflow-y set to hidden. Only if there is more content and we really need to scroll, then we set overflow-y to scroll.

If you now read above on what I wrote about the 'keyboard-open' class, I reckon that adding this class to the body tag and the reflow/repaint caused by this properly applies the overflow-y = hidden property value.

Second issue: Interestingly, there are 2 more lines in ionic.js which we have commented out as they lead to other but related issues:

https://github.com/driftyco/ionic/blob/master/release/js/ionic.js#L7145 and https://github.com/driftyco/ionic/blob/master/release/js/ionic.js#L7146:

      self.el.style.overflowY = 'hidden';
      self.el.style.overflowX = 'hidden';

Why did we do that? Sometimes these 2 lines, i.e. the first one of them setting overflow-y, lead to the situation that we could not scroll our ion-content anymore as the value hidden was kept and not set back to scroll. Nevertheless we need to the overflow-y to hidden when calling scrollTo(). Therefore we kind of rebuilt it in our own code. We now set the property to hidden, then call scrollTo(), then set the property back to scroll. In other words we are doing exactly the same, but now it always works and before we had the issue described above.

ionic info Cordova CLI: 5.4.1 Gulp version: CLI version 3.9.0 Gulp local: Local version 3.9.0 Ionic Version: 1.2.1 Ionic CLI Version: 1.7.11 Ionic App Lib Version: 0.6.5 ios-deploy version: 1.8.1 ios-sim version: 5.0.2 OS: Mac OS X El Capitan Node Version: v0.12.7 Xcode version: Xcode 7.1.1 Build version 7B1005

As our app is quite complex, it's not that easy to prepare a codepen/plunker. However, if someone, maybe @mhartington or @mlynch, is willing to look into this, I am happy to invest time to prepare something. The investigation so far and finding workarounds has taken quite some time already though.

Besides of that, Ionic is a really great framework :-)

Additional info: This happens in a chat module in our app, we have a text input in a footer bar but are not using the keyboard-attach directive but a similar directive we implemented by ourselves. Why? We wanted to have animated transitions for the scroller div bottom and the footer bar moving up with the keyboard. Just to give some more contextual information...

wxmerkt commented 8 years ago

+1 Experiencing exactly the same issue with 1.2.1-nightly under iOS9.2. We could mitigate it by adding style="overflow-y:hidden;" to our <ion-content> as suggested by @leschirmeur.

Ionic Info:

Your system information:

Cordova CLI: 5.3.3
Gulp version:  CLI version 3.9.0
Gulp local:   Local version 3.9.0
Ionic Version: 1.2.1-nightly-1867
Ionic CLI Version: 1.7.12
Ionic App Lib Version: 0.6.5
ios-deploy version: 1.5.0
ios-sim version: 3.1.1
OS: Mac OS X El Capitan
Node Version: v0.12.9
Xcode version: Xcode 7.2 Build version 7C68
$ ionic platform ls
Updated the hooks directory to have execute permissions
Installed platforms: android 4.1.1, ios 3.9.2
mlynch commented 8 years ago

Thanks, I've been looking into it today and making some progress thanks to your great comments. Stay tuned, will get this out in the next release

mlynch commented 8 years ago

I made a fix for this an hour ago, going to be in the next release. Please let me know if it doesn't resolve the issue for you.

DawidMyslak commented 8 years ago

Hi there,

I'm worried that this bug still occurs on iOS devices, I'm using iPhone 6 with latest iOS 9.2.1.

I've just started a new app using this command:

ionic start my-test-app sidemenu

Then I simply modified one of the template files (browse.html) and I added few input fields using examples from official docs, e.g:

<div class="list">
  <label class="item item-input">
    <span class="input-label">Test</span>
    <input type="text">
  </label>
  ...
</div>

So I run the app using Ionic View. Every time when I click on the input field (it's important to have few of them to make sure keyboard will cover at least one) the whole screen jumps.

I was also trying to use <ion-input> instead but didn't work too. This is official example app, so obviously this part is there as well:

if (window.cordova && window.cordova.plugins.Keyboard) {
  cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
  cordova.plugins.Keyboard.disableScroll(true);
}

More details about my environment:

$ ionic info

Cordova CLI: 6.0.0
Gulp version:  CLI version 3.9.0
Gulp local:
Ionic Version: 1.2.4
Ionic CLI Version: 1.7.14
Ionic App Lib Version: 0.7.0
OS: Windows 7 SP1
Node Version: v4.2.1
DawidMyslak commented 8 years ago

I've just created a new issue with more details: https://github.com/driftyco/ionic/issues/5489

tpanhorst commented 8 years ago

I am still having the issue with the white space after keyboard close, or when I move between inputs while the keyboard is opening.

DawidMyslak commented 8 years ago

@tpanhorst is it in Ionic View?

tpanhorst commented 8 years ago

@DawidMyslak No I've had the issue on my iPhone 5 iOS 9 device & iPhone 6 iOS 8 device. Turning off overflow-scroll on my ion-content (js scrolling) fixes the issue (except for some white flashing when closing the keyboard or changing rerending the view by changing tabs), but causes another issue where my content y origin is incorrect after the keyboard closes when the content is larger than the viewport.

lAndresul commented 8 years ago

This fix:

$ionicConfigProvider.scrolling.jsScrolling(true);

but maybe has an impact over the performance, what do you think guys?

iwan-uschka commented 8 years ago

I had problems with

$ionicConfigProvider.scrolling.jsScrolling(true);

with iframes in my scrollable content (e.g. youtube embed player). If user starts scrolling by tapping on iframe, it doesn't work. With

$ionicConfigProvider.scrolling.jsScrolling(false);

it works. The user can tap everywhere to start scrolling. So JS-Scrolling is no option if you have iframes embedded in your content.

DawidMyslak commented 8 years ago

Do not use $ionicConfigProvider.scrolling.jsScrolling(true);, it will turn off native scrolling in your app, which will affect the performance: http://ionicframework.com/docs/nightly/api/provider/$ionicConfigProvider/

What you really have to do is to make sure that your keyboard plugin is properly installed.

Open your app.js file and somewhere in the "run" function you should have the following code:

if (window.cordova && window.cordova.plugins.Keyboard) {
  cordova.plugins.Keyboard.disableScroll(true);
}

Try to use an "alert" function just to make sure that your plugin is there:

if (window.cordova && window.cordova.plugins.Keyboard) {
  alert('My keyboard plugin is working!');
  cordova.plugins.Keyboard.disableScroll(true);
}

Now, make a new build and run the app on your phone/simulator. From this stage, you have two options:

SquadraCorse commented 8 years ago

I have the same issue with 1.3.1 When form content is less then height of scrollable content it disappears when blurring input element (keyboard closes). In order to have a reflow i added this to my bottom form

<ion-item class="item-borderless hide-on-keyboard-open"> &nbsp; </ion-item>

which did the trick, as "pschuler" mentioned in forum

its still buggy because now and then the content will not even scroll at all (when form becomes bigger because of user input). I didnt experience it before because i used non native scrolling by default.

s4frul commented 8 years ago

Hi.. I'm also facing the same thing where the issue is:

And I'm was try my luck using simple fix by adding:style="height:90% !important;" into <ion-content> tag.. And its working fine now.. :)

Another alternative is by modified the code like this:

window.addEventListener('native.keyboardhide', keyboardHideHandler); function keyboardHideHandler(e){

var keyBoardGap = document.querySelector("#chatContainer"); keyBoardGap.classList.add("heightForce");
}

window.addEventListener('native.keyboardshow', keyboardShowHandler); function keyboardShowHandler(e){ var keyBoardGap = document.querySelector("#chatContainer"); keyBoardGap.classList.remove("heightForce"); }

CSS:

.heightForce { height:90% !important;}

Hope this helps others :)

iwan-uschka commented 8 years ago

i added this to my css

// iOS 9 fixes
.platform-ios {
  .scroll-content {
    > .scroll {
      min-height: 101%;
    }
  }
}

.overflow-scroll,
.overflow-scroll.pane {
  overflow-y: auto !important;
}

101% produces a scroll bar but it's worth it if you can fix this ugly issue, also it's better to use min-height instead of height to not limit vertical expansion of your content (but depends on content of course)