Alexandre Wiechers Vaz Alexandre Wiechers Vaz - 1 year ago 76
Android Question

Phonegap Android Application not adjusting pan on keyboardshow

I'm developing a phonegap application with version 2.9.0;

The layout was fully tested in desktop browser using RWD Bookmarklet( and worked fine. However, when tested in mobile devices or the emulator, the layout broke. After a little bit testing, I found out that the problem was the status bar height. Changed the application to fullscreen, problem solved.

But now, when i focus on an input field, the screen is not being adjusted, so, the keyboard covers the input field!

After looking all the questions and related problems, I found this one, that makes sense to me, but i wanted to know if there is a way to make the adjust pan work with fullscreen, so i don't need to adjust all my components height, calculate different status bar heights based on devices, etc.



<form id="login-form">
<div class="form-group">
<input type="text" name="login" class="form-control" id="login"
<div class="form-group">
<input type="password" name="pass" class="form-control"
id="password" placeholder="*******">
<a class="pull-right login-btn" id="btn-login" href="#"><span
<a class="pull-right login-btn" id="btn-cadastro" href="#"><span class="image-replacement"></span></a>

Android Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="" android:windowSoftInputMode="adjustPan"
package="" android:versionName="1.0" android:versionCode="1" android:hardwareAccelerated="true">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECORD_VIDEO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />

<application android:icon="@drawable/icon" android:label="@string/app_name"
<activity android:name="App" android:label="@string/app_name"
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17"/>


import org.apache.cordova.Config;
import org.apache.cordova.DroidGap;

import android.os.Bundle;
import android.view.WindowManager;

public class BDH extends DroidGap
public void onCreate(Bundle savedInstanceState)
// Set by <content src="index.html" /> in config.xml

getWindow().setFlags(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN, WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST);



Answer Source

Although it may be not the better way to fix it, i've found a solution. Detect the events and communicate to JS was not working for me, neither with window.scrollTo nor with the jQuery plugin. Unfortunately, my time is short and i preferred to do it in Java directly. As far as i have time, i'll refactor it and develop a plugin based on this solution. As the code gets updated, i'll update it here too. Here it goes:

     *  Due to a well known bug on Phonegap¹, android softKeyboard adjustPan functionality wasn't working
     *  as expected when an input field recieved focus. The common workaround(Change to adjustResize and),
     *  however, was not applicable, due to an Android bug² that crashes fullscreen apps when in adjustResize mode.
     *  This is an workaround, to detect when the softKeyboard is activated and then programatically scroll 
     *  whenever it needs;
     *  During the development proccess i came across an annoying behavior on android, that were making the
     *  input field dispatch onFocusChange twice when focus was cleared, when it should dispatch only once.
     *  The first one, without focus(Expected behavior), the second one WITH focus(Dafuq?), causing it to
     *  not scroll back on blur. My workaround was to only enable it to set a flag(lostFocus parameter), and
     *  only allow the method to calculate the scroll size IF the element had not lost it's focus;
     *  ¹ -
     *  ² -

    final View activityRootView = ((ViewGroup) findViewById(;

    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        public void onGlobalLayout(){

            View focused = appView.findFocus();

            if(focused instanceof TextView){

                if(focused.getOnFocusChangeListener() == null){
                    focused.setOnFocusChangeListener(new OnFocusChangeListener() {

                        public void onFocusChange(View v, boolean hasFocus) {
                                lostFocus = true;
                                showKeyBoard = false;
                                showKeyBoard = true;


                 *  Really tricky one to find, that was the only way i found to detect when this listener call came from
                 *  the buggy input focus gain. If the element had lost its focus, r(A Rect representing the screen visible area)
                 *  would be the total height, what means that there would be no keyboard to be shown, as far as the screen
                 *  was completely visible.
                if(showKeyBoard || != activityRootView.getHeight()){

                    int heightDiff = 0;
                    int keyBoardSize = 0;
                    int scrollTo = 0;

                    heightDiff = activityRootView.getRootView().getHeight() - focused.getTop();
                    keyBoardSize = activityRootView.getRootView().getHeight() - r.bottom;

                    if((keyBoardSize < focused.getBottom() && keyBoardSize > 0) && !lostFocus){
                        scrollTo = focused.getBottom() - keyBoardSize;

                    if(scrollTo == 0){
                        lostFocus = false;
                        showKeyBoard = true;
                    }else if(heightDiff < r.bottom){
                        activityRootView.scrollTo(0, scrollTo);
                        lostFocus = false;
                        showKeyBoard = false;

Elaboration on r, lostFocus and showKeyboard

r is a Rect object, that gets filled by the method getWindowVisibleDisplayFrame(Rect r)

From the Docs:

Retrieve the overall visible display size in which the window this view is attached to has been positioned in. This takes into account screen decorations above the window, for both cases where the window itself is being position inside of them or the window is being placed under then and covered insets are used for the window to position its content inside. In effect, this tells you the available area where content can be placed and remain visible to users.

So, if the keyboard is shown, r.bottom would be different from the rootView height.

showKeyboard and lostFocus are two workarounds to get reliably the correct focus/blur behavior. showKeyboard is simple, only a flag to tell the application if it should or should not scroll. Theoretically, it'd work, however, i came across an annoying bug, that caused the input field to be focused immediately after his lost of focus, before the soft keyboard hide (Only internally in the application, on device, the element didn't gain focus and the keyboard was already hidden). To solve it, i've used lostFocus to tell the application when it really has lost focus and only allow it to calculate where to scroll if the element hadn't lost its focus.