PhoneGap的Andr​​oid应用程序不能在keyboardshow调整盘 [英] Phonegap Android Application not adjusting pan on keyboardshow

查看:178
本文介绍了PhoneGap的Andr​​oid应用程序不能在keyboardshow调整盘的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发展与2.9.0版本的PhoneGap应用;

I'm developing a phonegap application with version 2.9.0;

布局是完全的桌面浏览器中使用RWD小书签测试( http://responsive.victorcoulon.fr/ )和精细工作。然而,当在移动设备或仿真器进行测试,布局爆发。经过一点点的测试,我发现这个问题是状态栏的高度。改变了应用程序以全屏幕,问题就解决了​​。

The layout was fully tested in desktop browser using RWD Bookmarklet(http://responsive.victorcoulon.fr/) 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!

在看所有的问题和相关问题,我发现<一href="http://stackoverflow.com/questions/15749423/keyboard-does-not-pan-on-android-application-using-phonegap">this一个,那对我来说很有意义,但我想知道是否有一种方法,使与全屏的调整平移工作,所以我并不需要调整我的所有组成部分的高度,计算基于设备等不同的状态栏的高度

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.

codeS

form.html

<form id="login-form">
    <div class="form-group">
       <input type="text" name="login" class="form-control" id="login"
                        placeholder="xxxxxxx@xxx.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>

安卓的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> 

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")
    }
}

任何帮助将是非常非常多的AP preciated!

Any help would be very, very much appreciated!

在此先感谢, 亚历山大

Thanks in advance, Alexandre

推荐答案

虽然可能没有更好的办法来解决这个问题,我已经找到了解决办法。检测的事件,并传达给JS是不是为我工作,既不window.scrollTo也不与jQuery插件。不幸的是,我的时间很短,I $ pferred直接做在Java中p $。至于我有时间,我会重构,并开发基于该解决方案的一个插件。由于code被更新,我会在这里更新了。这里有云:

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;
     * 
     *  ¹ - http://stackoverflow.com/questions/11968420/softkeyboard-in-phonegap-covers-input-elements
     *  ² - http://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible
     **/

    final View activityRootView = ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0);

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

            View focused = appView.findFocus();
            activityRootView.getWindowVisibleDisplayFrame(r);

            if(focused instanceof TextView){

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

                        @Override
                        public void onFocusChange(View v, boolean hasFocus) {
                            if(!hasFocus){
                                activityRootView.scrollTo(0,0);
                                lostFocus = true;
                                showKeyBoard = false;
                            }else{
                                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 || r.top != 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){
                        activityRootView.scrollTo(0,scrollTo);
                        lostFocus = false;
                        showKeyBoard = true;
                    }else if(heightDiff < r.bottom){
                        activityRootView.scrollTo(0, scrollTo);
                        lostFocus = false;
                        showKeyBoard = false;
                    }
                }
            }
        }
    });

在R,引发LostFocus和showKeyboard 制定

Elaboration on r, lostFocus and showKeyboard

研究的是一个矩形对象,即得到填补的方法的 <一个href="http://developer.android.com/reference/android/view/View.html#getWindowVisibleDisplayFrame%28android.graphics.Rect%29"相对=nofollow> getWindowVisibleDisplayFrame(矩形R)

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

从文档:

检索整个可见显示大小,其中窗口此   视图附着到已被定位在。这是考虑到   屏幕上的装饰,在窗口上方,这两种情况下,其中的窗口   本身正在位置他们的内部或窗口被放置   下然后和覆盖插图被用于窗口以定位其   里面的内容。 实际上,这告诉你的可用区域   内容可以被放置并保持对用户可见。

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.

因此​​,如果键盘被示出,的 r.bottom 的将是从rootView高度不同。

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

showKeyboard 引发LostFocus 的两种解决方法得到可靠正确的焦点/模糊行为。 showKeyboard 的很简单,只有一个标志是否应该或不应该滚动告诉应用程序。从理论上讲,它会工作,但是,我碰到一个恼人的bug,导致输入字段被他后,立即集中在应用程序失去焦点,软键盘隐藏前(只在内部,上设备,元件没牛逼获取焦点和键盘已隐藏)。为了解决这个问题,我用引发LostFocus告诉应用程序时,它确实已经失去焦点,只允许它来计算,其中滚动如果元素没有失去它的焦点。

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.

这篇关于PhoneGap的Andr​​oid应用程序不能在keyboardshow调整盘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆