我正在开发一个版本为2.9.0的phonegap应用程序;
该布局在桌面浏览器中使用RWD Bookmarklet(http://responsive.victorcoulon.fr/)进行了充分测试,并运行良好。但是,当在移动设备或模拟器中进行测试时,布局会中断。经过一点测试,我发现问题在于状态栏的高度。将应用程序改为全屏,解决了问题。
但是现在,当我关注一个输入字段时,屏幕没有被调整,所以键盘覆盖了输入字段!
在查看了所有问题和相关问题之后,我找到了这 one,这对我来说很有意义,但我想知道是否有办法使调整盘与全屏工作,所以我不需要调整所有组件的高度,根据设备计算不同的状态栏高度等等。
码
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>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> 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")
}
}发布于 2013-09-16 15:59:11
虽然这可能不是修复它的更好方法,但我已经找到了解决方案。检测这些事件并与JS沟通对我来说是行不通的,window.scrollTo和jQuery插件也不起作用。不幸的是,我的时间很短,我更喜欢用Java直接做。只要我有时间,我将重构它,并开发一个基于这个解决方案的插件。随着代码的更新,我也会在这里更新它。下面是:
/**
*
* 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的lostFocus阐述
R是一个Rect对象,它由方法http://developer.android.com/reference/android/view/View.html#getWindowVisibleDisplayFrame%28android.graphics.Rect%29填充。
来自“文件”:
检索该视图所附加到的窗口所在的总体可见显示大小。这将考虑到窗口上方的屏幕装饰,因为无论是窗口本身在窗口内部的位置,还是窗口被放置在窗口下面的情况下,都会使用覆盖的嵌入式来将其内容放置在窗口中。实际上,这告诉您可以放置内容并保持用户可见的可用区域。。
因此,如果显示键盘,r.bottom将与rootView高度不同。
showKeyboard和lostFocus是获得可靠的焦点/模糊行为的两个解决方案。showKeyboard很简单,只有一个标志可以告诉应用程序是否应该滚动。但从理论上讲,我遇到了一个令人讨厌的错误,它导致输入字段在他失去焦点后,在软键盘隐藏之前(仅在应用程序内部,在设备上,元素没有获得焦点,键盘已经被隐藏)。为了解决这个问题,我使用lostFocus来告诉应用程序它确实失去了焦点,并且只允许它计算如果元素没有失去焦点就滚动到哪里。
发布于 2013-09-04 09:41:56
更新
按照我最初的回答,下面的JavaScript将在windowSoftInputMode="adjustResize"上工作,但是它不会在"adjustPan"上工作,因为显示键盘时不会触发JavaScript resize()事件。
但是,正如前面提到的这里,您可以通过将GlobalLayoutListener链接到ViewTreeObserver来捕获ViewTreeObserver端显示的键盘事件。
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")
final View activityRootView = ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout()
{
// r will be populated with the coordinates of your view that area still visible.
Rect r = new Rect();
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
// If more than 100 pixels, its probably a keyboard...
if (heightDiff > 100)
{
// Fire off a function to the JavaScript.
this.sendJavascript("try { onKeyboardShowing(); } catch (e) {};");
}
}
});
}
}因此,当显示键盘时,您可以向JavaScript发出一个函数,指示正在显示的键盘,然后您可以调整屏幕:
var fieldFocused = null;
function onKeyboardShowing()
{
if(fieldFocused != null)
{
$('body').scrollTo(fieldFocused, 500, {offset:-50});
}
}
$(document).on('focus', 'input, textarea', function() {
fieldFocused = $(this);
});
$(document).on('blur', 'input, textarea', function() {
fieldFocused = null;
});原始答案
我们很难修复覆盖输入字段的Android软键盘。我想出的解决办法绝不是“很好”,不管效果如何.
你将需要jQuery和另一个名为jQuery.ScrollTo的jQuery插件,由Ariel开发,这里。
现在将其添加到JavaScript中:
var fieldFocused = null;
$(window).resize(function(e) {
if(fieldFocused != null)
{
$('body').scrollTo(fieldFocused, 500, {offset:-50});
}
});
$(document).on('focus', 'input, textarea', function() {
fieldFocused = $(this);
});
$(document).on('blur', 'input, textarea', function() {
fieldFocused = null;
});当一个textarea/input被聚焦时,DOM元素被分配给一个变量。当调整窗口的大小时,窗口将被滚动以将DOM元素带到顶部。
我们在Android清单中使用了android:windowSoftInputMode="adjustResize“。
正如我已经说过的,这不是最优雅的修复,但我们已经实现到我们的PhoneGap应用程序和它的工作。
发布于 2013-11-10 16:22:39
刚刚将解决方案发布在:http://www.stackoverflow.com/questions/19849462/上
https://stackoverflow.com/questions/18599519
复制相似问题