16

I've tried many different solutions and nothing is quite what I want. What I want is for the keyboard to show on top of the content (keeping the content the same size) while being able to scroll to input elements that are covered by the keyboard.

Every solution I've tried will either give me one or the other, but not both.

Solutions I've tried:

  • Solution here. Adding android:windowSoftInputMode="adjustPan" and android:configChanges="orientation|keyboardHidden" to the main activity in my AndroidManifest.xml.
  • The above solution using "adjustResize" instead of "adjustPan".
  • Solution here. Adding to my confix.xml.

Using adjustPan keeps my elements the same size, but disables scrolling. Using adjustResize resizes the entire page, making everything miniature. Keeping default settings, only the wrapper containing the input elements is resized, but scrolling is enabled.

I managed to find the exact same problem (unanswered) here. They were able to "fix" it by resizing their app to 150% and scroll to the covered input element, but like they said it's not ideal.

Any help is appreciated.

Community
  • 1
  • 1
cohenadair
  • 2,072
  • 1
  • 22
  • 38

10 Answers10

12

For most of the cases in config.xml change the full screen preference to false. that'll do the trick.

<preference name="fullscreen" value="false" />
Sameera R.
  • 4,384
  • 2
  • 36
  • 53
  • 1
    Yes this makes the content scroll but how about the fullscreen scenario ? I could not succeded that . When I make my app fullscreen input is not pushed up. – katmanco Oct 10 '18 at 07:35
12

I have the most efficient solution to scroll into input automatically and make it visible. First you need to add the ionic keyboard plugin (works on any cordova project) because the eventlistener 'showkeyboard' does not work now.

cordova plugin add ionic-plugin-keyboard --save

Then on your event handler of 'keyboardshow' event add the following code:

window.addEventListener('native.keyboardshow', function(e){ 
    setTimeout(function() {
        document.activeElement.scrollIntoViewIfNeeded();
    }, 100);
});

P.S: This is supported only on Android (Chrome) and Safari. :D

Biswas Khayargoli
  • 976
  • 1
  • 11
  • 29
7

I had the same problem for android project output and in my situation the input elements were not moving upwards the keyboard . And after a-night-taking search (including those config changes and others) I found that in my angularjs cordova project

StatusBar.overlaysWebView(true);
StatusBar.hide();

lines which are in my controller causing that annoying problem . And I was using those lines for ios statusbar issues now I took those in an if condition and the problem is fixed.

if( device.platform=="iOS")
  {
   StatusBar.overlaysWebView(true);
   StatusBar.hide();
  }
katmanco
  • 1,146
  • 12
  • 24
  • 2
    You just save my life man, thanks. Don't understand why the status bar would affect the application like that, that's really a shame on the cordova side... – sjahan Jul 12 '18 at 09:42
  • 2
    same issue here... its crazy this issue. – jremi Aug 27 '18 at 06:43
4

You can detect focused textarea or input, then wait a while until keyboard is shown and finally scroll the page to reach focused input.

$("#textarea").focus(function(e) {
    var container = $('#container'),
        scrollTo = $('#textarea');

    setTimeout((function() {
        container.animate({
        scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop()
        });
    }), 500);

});

When keyboard is hidden the textarea keeps focused, so if it's clicked again the keyboard will show and the container needs to scroll again to show the input

$("#textarea").click(function(e) {
    e.stopPropagation();
    var container = $('#container'), //container element to be scrolled, contains input
        scrollTo = $('#textarea');

    setTimeout((function() {
        container.animate({
        scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop()
        });
    }), 500);
});

Hope this helps, cheers!

Jose Rojas
  • 3,490
  • 3
  • 26
  • 40
dianakarenms
  • 2,609
  • 1
  • 22
  • 22
3

I added an event listener for the keyboard event and scrolled to the input only if it was off screen.

For my case I only wanted to scroll when the keyboard was being shown for the first time, and only if the input item was offscreen.

document.addEventListener('showkeyboard', onKeyboardShow, false);


 function onKeyboardShow(e) {        
    setTimeout(function() {
      e.target.activeElement.scrollIntoViewIfNeeded()
    }, 500) //needed timeout to wait for viewport to resize
  }

To get the showkeyboard event to fire I needed to have the following in my AndroidManifest.xml

  android:windowSoftInputMode="adjustResize"
Greg L
  • 381
  • 4
  • 5
0

I was also facing the same issue as it is a framework related issue. I have found work around-

constructor(
        private platform: Platform,
        private keyboard: Keyboard
      ) {
        if(this.platform.is('android')){
          this.keyboard.onKeyboardShow().subscribe((e) => {
             var keyboardHeight = e.keyboardHeight;
             keyboardHeight = keyboardHeight ? keyboardHeight : '337';
             $('body').css('height', 'calc(100vh - ' + keyboardHeight + 'px)');    
      });

      this.keyboard.onKeyboardHide().subscribe(e => {
       $("body").css("height", "100vh");
      });
    }
}

I have used 337 which is keyboard height for default, mainly for that condition if keyboard height in not available.

library needed:

    npm install jquery
    npm install @types/jquery
    ionic cordova plugin add cordova-plugin-ionic-keyboard
    npm install @ionic-native/keyboard

imports

    import { Platform } from '@ionic/angular';
    import * as $ from "jquery";
    import { Keyboard } from '@ionic-native/keyboard/ngx';
Kshitij
  • 360
  • 4
  • 12
0

I came up with this solution. I have a full screen Vuejs application which the container has the height of the screen height and then absolute positioned to the bottom, left and right to fix the same sort of issue on IOS.

I then had the same issue on Android so came up with the following;

window.cordovaPluginIonicKeyboardShift = function()
{
    /** This is my container (Vuejs instance) **/
    const inst = document.querySelector('#app');

    /** Get the height of the document **/
    const height = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);

    /** Where we will store the active input **/
    let input;

    /** The keyboard displaying is around 200 milliseconds **/
    inst.style.transition = 'transform 0.2s';

    /** Makes me feel better having this on to increase performance **/
    inst.style.transform = 'translateZ(0)';

    /**
     * Set Input
     * @param e
     */
    let setInput = function(e) {
        input = e.target;
    };

    /**
     * On Keyboard Show
     * @param event
     */
    let onKeyboardShow = function(event) {
        let offset = input.getBoundingClientRect();
        if(offset.top + input.clientHeight > height - event.keyboardHeight) {
            inst.style.transform = `translateZ(0) translateY(-${event.keyboardHeight}px)`;
        }
    };

    /**
     * OnKeyboard Hide
     */
    let onKeyboardHide = function() {
        inst.style.transform = `translateZ(0) translateY(0px)`;
    };

    /**
     * Hide Keyboard
     * @param e
     */
    let hideKeyboard = function(e) {
        if(e.target.tagName.toLowerCase() !== 'input' && e.target.tagName.toLowerCase() !== 'textarea') {
            if(typeof input !== 'undefined') input.blur();
            if(Keyboard.isVisible) Keyboard.hide();
        }
    };

    /**
     * Go through all inputs and textarea's on document and attach touchstart
     * event. Using touchstart to define the input before focus which is what will trigger
     * the keyboard.
     */
    inst.querySelectorAll('input, textarea').forEach(function(elm) {
        elm.removeEventListener('touchstart', setInput, false);
        elm.addEventListener('touchstart', setInput, false);
    });

    /**
     * Need to get the height to shift the document up by x amount
     */
    window.removeEventListener('keyboardWillShow', onKeyboardShow, false);
    window.addEventListener('keyboardWillShow', onKeyboardShow, false);

    /**
     * Shift it back down on keyboard hiding
     */
    window.removeEventListener('keyboardWillHide', onKeyboardHide, false);
    window.addEventListener('keyboardWillHide', onKeyboardHide, false);

    /**
     * Some browsers/phone models act odd when touching off the input
     * so this is in to cover all bases
     */
    document.removeEventListener('touchstart', hideKeyboard, false);
    document.addEventListener('touchstart', hideKeyboard, false);

};

It also turns out even installing the plugin has affected the normal use of the keyboard which is why the hide method is called as the keyboard doesn't go away without it.

Then on my Vuejs instances I have the following updated method;

updated: function () {
    this.$nextTick(function () {
        cordovaPluginIonicKeyboardShift();
    })
},

You'll also need to add this plugin;

phonegap cordova plugin add cordova-plugin-ionic-keyboard

Doing the above I have a successfully working fullscreen app with a working keyboard.

If you find yourself testing on Xcode Simulator and the keyboard is not showing, go to Simulator -> Device -> Erase all content and settings and re-install the app. No idea why this occurs but this will save you a lot of head aches.

phone.gif

Hope this helps someone

Luke Snowden
  • 4,056
  • 2
  • 37
  • 70
-1

I figured out the problem. I have a media query in my CSS where the size of certain elements change for smaller screen sizes. Editing that query fixed my problem.

cohenadair
  • 2,072
  • 1
  • 22
  • 38
  • 4
    Can you share more specifics? Which kind of elements? Editing it how? I'm encountering a similar problem, but can't figure out which media queries need tweaking in what kind of way. – nkoren Dec 04 '14 at 12:53
  • I edited the query condition so it excluded the smaller screen when the keyboard appeared. – cohenadair Dec 04 '14 at 22:39
-1

I am using the Cordova plugin 'ionic-plugin-keyboard' and listen to the 'native.keyboardshow' and 'native.keyboardhide' events to resize the HTML container element of my form:

    window.addEventListener('native.keyboardshow', function (e) {
        container.style.bottom = e.keyboardHeight + "px";
    });

    window.addEventListener('native.keyboardhide', function () {
        container.style.bottom = null;
    });

This results in the proper input fields to scroll into view (also when tabbing back and forward between the fields.

-5

If you have made correctly the project as Cordova documentation says, It won't happen.

May be are you using a scroll library like iScroll?

pianista
  • 108
  • 8
  • The only libraries I'm using are Google Maps, jQuery Mobile (removing makes no difference), and jQuery. I've been messing with settings so maybe if I reset everything back to default it'll work. I'll try that. – cohenadair May 29 '14 at 15:20
  • Unfortunately that didn't make a difference. It has to be something to do with a resize event when the keyboard appears. I haven't been able to find if there's a way to disable it, though. – cohenadair May 29 '14 at 15:47