Phonegap Android应用程序没有在键盘秀上调整平移

Ale*_*Vaz 6 android cordova

我正在开发版本为2.9.0的phonegap应用程序;

使用RWD Bookmarklet(http://responsive.victorcoulon.fr/)在桌面浏览器中对布局进行了全面测试,并且工作正常.但是,在移动设备或仿真器中进行测试时,布局中断了.经过一点点测试,我发现问题是状态栏的高度.将应用程序更改为全屏,问题解决了.

但是现在,当我专注于输入字段时,屏幕没有被调整,因此,键盘覆盖输入字段!

在查看了所有问题和相关问题之后,我找到了这个,这对我来说很有意义,但我想知道是否有办法让调整盘全屏工作,所以我不需要调整我的所有组件高度,根据设备等计算不同的状态栏高度

代码

form.html

<form id="login-form">
    <div class="form-group">
       <input type="text" name="login" class="form-control" id="login"
                        placeholder="xxxxxxx@example.com">
    </div>
    <div class="form-group">
      <input type="password" name="pass" class="form-control"
                        id="password" placeholder="*******">
    </div>
    <a class="pull-right login-btn" id="btn-login" href="#"><span
                    class="image-replacement"></span></a> 
    <a class="pull-right login-btn" id="btn-cadastro" href="#"><span class="image-replacement"></span></a>
</form>
Run Code Online (Sandbox Code Playgroud)

Android Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
      package="com.com.app" android:versionName="1.0" android:versionCode="1" android:hardwareAccelerated="true">
    <supports-screens
        android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true"
        android:xlargeScreens="true"
        android:resizeable="true"
        android:anyDensity="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"
    android:hardwareAccelerated="true"
    android:debuggable="true">
    <activity android:name="App" android:label="@string/app_name"
            android:theme="@android:style/Theme.Black.NoTitleBar"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"
            android:windowSoftInputMode="stateVisible|adjustPan">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17"/>
</manifest> 
Run Code Online (Sandbox Code Playgroud)

App.java

package com.com.app;

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

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

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

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

        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

        super.loadUrl(Config.getStartUrl());
        //super.loadUrl("file:///android_asset/www/index.html")
    }
}
Run Code Online (Sandbox Code Playgroud)

Ale*_*Vaz 2

虽然这可能不是更好的解决方法,但我已经找到了解决方案。检测事件并与 JS 通信对我来说不起作用,无论是使用 window.scrollTo 还是使用 jQuery 插件。不幸的是,我的时间很短,我更喜欢直接用 Java 来做。只要我有时间,我将重构它并基于此解决方案开发一个插件。随着代码更新,我也会在这里更新。事情是这样的:

\n\n
    /**\n     * \n     *  Due to a well known bug on Phonegap\xc2\xb9, android softKeyboard adjustPan functionality wasn\'t working\n     *  as expected when an input field recieved focus. The common workaround(Change to adjustResize and),\n     *  however, was not applicable, due to an Android bug\xc2\xb2 that crashes fullscreen apps when in adjustResize mode.\n     *  This is an workaround, to detect when the softKeyboard is activated and then programatically scroll \n     *  whenever it needs;\n     *\n     *  During the development proccess i came across an annoying behavior on android, that were making the\n     *  input field dispatch onFocusChange twice when focus was cleared, when it should dispatch only once.\n     *  The first one, without focus(Expected behavior), the second one WITH focus(Dafuq?), causing it to\n     *  not scroll back on blur. My workaround was to only enable it to set a flag(lostFocus parameter), and\n     *  only allow the method to calculate the scroll size IF the element had not lost it\'s focus;\n     * \n     *  \xc2\xb9 - http://stackoverflow.com/questions/11968420/softkeyboard-in-phonegap-covers-input-elements\n     *  \xc2\xb2 - http://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible\n     **/\n\n    final View activityRootView = ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0);\n\n    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {\n        @Override\n        public void onGlobalLayout(){\n\n            View focused = appView.findFocus();\n            activityRootView.getWindowVisibleDisplayFrame(r);\n\n            if(focused instanceof TextView){\n\n                if(focused.getOnFocusChangeListener() == null){\n                    focused.setOnFocusChangeListener(new OnFocusChangeListener() {\n\n                        @Override\n                        public void onFocusChange(View v, boolean hasFocus) {\n                            if(!hasFocus){\n                                activityRootView.scrollTo(0,0);\n                                lostFocus = true;\n                                showKeyBoard = false;\n                            }else{\n                                showKeyBoard = true;\n                            }\n                        }\n\n                    });\n                }\n\n                /**\n                 * \n                 *  Really tricky one to find, that was the only way i found to detect when this listener call came from\n                 *  the buggy input focus gain. If the element had lost its focus, r(A Rect representing the screen visible area)\n                 *  would be the total height, what means that there would be no keyboard to be shown, as far as the screen\n                 *  was completely visible.\n                 * \n                 **/\n                if(showKeyBoard || r.top != activityRootView.getHeight()){\n\n                    int heightDiff = 0;\n                    int keyBoardSize = 0;\n                    int scrollTo = 0;\n\n\n                    heightDiff = activityRootView.getRootView().getHeight() - focused.getTop();\n                    keyBoardSize = activityRootView.getRootView().getHeight() - r.bottom;\n\n                    if((keyBoardSize < focused.getBottom() && keyBoardSize > 0) && !lostFocus){\n                        scrollTo = focused.getBottom() - keyBoardSize;\n                    }\n\n\n                    if(scrollTo == 0){\n                        activityRootView.scrollTo(0,scrollTo);\n                        lostFocus = false;\n                        showKeyBoard = true;\n                    }else if(heightDiff < r.bottom){\n                        activityRootView.scrollTo(0, scrollTo);\n                        lostFocus = false;\n                        showKeyBoard = false;\n                    }\n                }\n            }\n        }\n    });\n
Run Code Online (Sandbox Code Playgroud)\n\n

r、lostFocus 和 showKeyboard 的阐述

\n\n

r是一个 Rect 对象,通过getWindowVisibleDisplayFrame(Rect r)方法填充

\n\n

来自文档:

\n\n
\n

检索该视图附加到的窗口所在的整体可见显示大小。这考虑了窗口上方的屏幕装饰,对于窗口本身位于其中的两种情况或窗口被放置在\n 下面,并且覆盖的插图用于窗口将其内容\n 放置在其中。实际上,这告诉您可以放置​​内容并对用户保持可见的可用区域。

\n
\n\n

因此,如果显示键盘,r.bottom将与 rootView 高度不同。

\n\n

showKeyboardlostFocus是两种解决方法,可以可靠地获得正确的焦点/模糊行为。showKeyboard很简单,只有一个标志来告诉应用程序是否应该滚动。从理论上讲,它可以工作,但是,我遇到了一个恼人的错误,该错误导致输入字段在失去焦点后、在软键盘隐藏之前立即聚焦(仅在应用程序内部、在设备上,该元素没有\ 无法获得焦点并且键盘已经隐藏)。为了解决这个问题,我使用lostFocus来告诉应用程序它何时真正失去了焦点,并且仅允许它计算在元素没有失去焦点的情况下滚动的位置。

\n