12

In iOS 6 everything works fine. The keyboard opens and moves the input into view. When the keyboard closes everything goes back where it should.

In iOS 7 the keyboard opens fine and the input remains in view. When the keyboard is closed the whole bottom half of the app is gone, though. I've tracked the issue down to the height of the window changing when the keyboard is opened, and not changing back when it's closed.

Right before the keyboard is opened the window height is 568 according to $(window).height() and after it's opened and after it's closed it is 828. The height of the document also changes accordingly.

I've attempted preventing the window from resizing with:

$(window).resize(function(e) {
   e.preventDefault();
   e.stopPropagation();
   window.resizeTo(320,480);
   return false;
});

I've also attempted to set the size back after the keyboard closes with no success.

I'm using phonegap 2.7 and have KeyboardShrinksView set to true.

jdehlin
  • 10,909
  • 3
  • 22
  • 33
  • Right now my plan is to download an Xcode 4.6, pull the iOS6 SDK out of it, and build with that. Any solution to the actual problem are greatly appreciated though. – jdehlin Oct 03 '13 at 22:56
  • It's not really an answer to the issue but I've worked around this by setting the app to build with iOS 6.1 as the Base SDK and things are working as expected. – jdehlin Oct 04 '13 at 00:35

9 Answers9

7

I was seeing this too. After the height changes, some of our absolute positioned elements disappear off the bottom of the screen.

I found that with KeyBoardShrinksView = false in ios7, window.height stayed constant. This was the opposite of ios6 though, so a bit of a catch 22.

Not sure if there's a better way of handling this in Phonegap, but I put this in CDVViewController.m, created to config.xml files for ios < v7 and ios > v6, and my app works the way I want. Seemed a bit hacky, but not too disruptive of the rest of my code.

// read from config.xml in the app bundle
NSString* path = [[NSBundle mainBundle] pathForResource:@"config" ofType:@"xml"];

if (IsAtLeastiOSVersion(@"7.0")) {
    path = [[NSBundle mainBundle] pathForResource:@"config_ios7" ofType:@"xml"];
}

(I also tried an app preference plugin at https://github.com/phonegap/phonegap-plugins/tree/master/iPhone/ApplicationPreferences but don't think this was designed for this kind of preference.)

Paul
  • 494
  • 5
  • 8
  • 1
    I still don't have a complete solution either though. Another part of my app has the same issue as you where I lose the bottom of my page completely after a keyboard hide. To complicate things, toggling KeyBoardShrinksView makes this scenario work ok in ios7, but not so well in ios6... – Paul Oct 05 '13 at 03:27
  • 3
    Answering my own stuff again, but on further investigation I found that adding height=device-height in the viewport meta tag of my application html page fixed the problem of stuff getting chopped off the bottom of the page. Weirdly, KeyboardShrinksView = false seems to work better for me in ios7. Despite the setting 'false', the view seemed to resize quite nicely when the keyboard was active. With this combination, my ios7 version app actually works better then earlier versions now. (I'm using phonegap 2.7 too.) – Paul Oct 08 '13 at 00:03
  • I didn't end up doing this but it seems like a viable solution. – jdehlin Oct 25 '13 at 17:29
5

After I upgraded my project to iOS with cordova 3.1 I start having similar problems for the input fields in where I did not have the code listed above. The keyboard pushes things up and the header and footer did not returned to their original positions. I have tested and that solve the problem (maybe not very elegantly but it is a workaround). I just put that code on my pageinit event.

 /************************************************************************************************* 
 * FIX: to avoid the buggy header and footer to jump and stick not
 * to the top/bottom of the page after an input or textfield lost focus and the keyboard dissapear                          *
 *************************************************************************************************/ 
 $('input, textarea')
 .on('focus', function (e) {
    $('header, footer').css('position', 'absolute');
 })
 .on('blur', function (e) {
    $('header, footer').css('position', 'fixed');
    //force page redraw to fix incorrectly positioned fixed elements
    setTimeout( function() {
        window.scrollTo( $.mobile.window.scrollLeft(), $.mobile.window.scrollTop() );
    }, 20 );
 });
VicM
  • 2,449
  • 1
  • 18
  • 20
  • 2
    Thank you, had this problem forever with a few HTML5 webapps (not Cordoba/Phonegap) and your solution worked perfectly. – LP Papillon May 01 '14 at 19:51
  • Where should I put this code? I am new to phone gap and facing this issue. Thanks in advance – Navnath Memane Jun 03 '14 at 13:04
  • inside your Javascript file, and the JS file should be included in the html page, like any regular web page. Be sure to put the code inside your on page ready function. – VicM Jun 03 '14 at 17:44
3

add code into CDVViewController.m for example it added into webViewDidFinishLoad function

CGRect newFrame = self.webView.bounds;
NSLog(@"%f" , newFrame.size.height);

NSString *JS =  [NSString stringWithFormat:@"viewport = document.querySelector('meta[name=viewport]'); viewport.setAttribute('content', 'user-scalable=no, initial-scale=1.0, maximum-scale=0.5, minimum-scale=0.5, width=device-width, height=%d,  target-densitydpi=device-dpi');",  (int) newFrame.size.height*2 ];

[self.webView stringByEvaluatingJavaScriptFromString:JS];

this code change <meta name="viewport" content="..."> and set height of device

2

set your viewport meta tag to your html

<meta name="viewport" content="width=device-width,height=**yourheight**, initial-scale=1, maximum-scale=1, user-scalable=0" >

or

<meta name="viewport" content="width=device-width,height=**device-height**, initial-scale=1, maximum-scale=1, user-scalable=0" >
Nathan H
  • 48,033
  • 60
  • 165
  • 247
  • 1
    I used device-height and it didn't seem to have any affect. Also, there is an issue with iPhone only apps running on iPad where only a small portion of the app is visible when height=device-height is set in iOS7. My app was actually rejected due to this so I had to remove that setting. – jdehlin Oct 09 '13 at 13:24
2

The Petrash's solution worked for me. But I had still problems supporting rotations on iPad. So, in the same CDVViewController.m I've added this method:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
    if (self.webView){
        CGRect newFrame = self.webView.bounds;
        //NSLog(@"%f" , newFrame.size.height);

        NSString *JS =  [NSString stringWithFormat:@"viewport = document.querySelector('meta[name=viewport]'); viewport.setAttribute('content', 'user-scalable=no, initial-scale=1.0, maximum-scale=1, minimum-scale=1, width=device-width, height=%d,  target-densitydpi=device-dpi');",  (int) newFrame.size.height*1 ];

        [self.webView stringByEvaluatingJavaScriptFromString:JS];
    }

}

and, to support the "non scale" behaviour, edited the Petrash's solution in this way:

CGRect newFrame = self.webView.bounds;
    //NSLog(@"%f" , newFrame.size.height);

    NSString *JS =  [NSString stringWithFormat:@"viewport = document.querySelector('meta[name=viewport]'); viewport.setAttribute('content', 'user-scalable=no, initial-scale=1.0, maximum-scale=1, minimum-scale=1, width=device-width, height=%d,  target-densitydpi=device-dpi');",  (int) newFrame.size.height*1 ];

    [self.webView stringByEvaluatingJavaScriptFromString:JS];

KeyboardShrinksView = false

This is hacky, but it works from 5.1 to 7.0.3. Tested on Cordova 3.0.

Andrea
  • 326
  • 3
  • 9
2

After hours of investigating I've managed to get it to work:

My div, that is pushed up and never get's down again, had the css attribute

position:fixed;

I switched this to

position:absolute;

and everything worked!

David Vielhuber
  • 3,253
  • 3
  • 29
  • 34
1

The best way I found was to put everything into a div and fix its height via javascript. Works on modern Versions of both iOS (5, 6, 7) and Android (4.2, ...).

<style>
    body {
        overflow-y: scroll;
        overflow-x: hidden;
        webkit-overflow-scrolling: touch;
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
    }

    body > .viewport{
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
    }
</style>

<body>
    <div class='viewport'>
        <!-- Put everything here -->
    </div>
</body>

<script type="text/javascript">
    $("body > .viewport").height($(document).height());
    // WARNING: if your app works in both landscape and portrait modus, then you should reset the height of the container when the app changes orientation
</script>
david
  • 944
  • 6
  • 8
0

I had a similar issue that drove me nuts for days. Not sure if this will help anyone else, but this is what solved it for me: (note I'm using jquery finger library to listen to tap events):

$('body').delegate("#send_feedback_button","tap", function(event){
  $('textarea').blur();
  event.stopImmediatePropagation();
  // do my stuff 
});

For me calling blur on any textarea in the view was the trick. The stopImmediatePropagation got rid of some other funkiness.

DemitryT
  • 391
  • 4
  • 17
0

I had the same problem and I managed to track it down to dynamic content. I had initially an empty div that was filled with text using javascript. When I pre filled the div with static text the problem was gone.

Looks like this div's height was not counted when resizing.