在Android中,是否有一种方法可以在运行时获取设备上显示的虚拟键盘的高度?实际上,我想在键盘上方显示一个文本框。
我尝试了很多建议的方法,但似乎都不适用于Android SDL。我认为这可能是因为SDL显示是“全屏”的,或者它位于“AbsoluteLayout”中,因此“View”的高度实际上从未更改。这种方法对我有效:
Window mRootWindow = getWindow();
View mRootView = mRootWindow.getDecorView().findViewById(android.R.id.content);
mRootView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout(){
Rect r = new Rect();
View view = mRootWindow.getDecorView();
view.getWindowVisibleDisplayFrame(r);
// r.left, r.top, r.right, r.bottom
}
});
使用Viewtree Observer和全局布局监听器,您可以实现这一点,只需按照以下步骤尝试即可:
现在,每当Android显示软键盘时,它会重新调整屏幕大小并在监听器上调用您。这就是全部要做的事情,现在您需要做的唯一一件事情是计算在重新调整大小后您的根视图高度与原始大小之间的差异。如果差异大于150,则将其视为键盘已充气。
以下是示例代码:
root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){
public void onGlobalLayout(){
int heightDiff = root.getRootView().getHeight()- root.getHeight();
// IF height diff is more then 150, consider keyboard as visible.
}
});
敬礼, Techfist
120dp
,这在Nexus 7(xhdpi)和Nexus 5(xxhdpi)上效果很好。但你的经验可能会有所不同... - Thomas Keller通过新的窗口插图API,这非常简单:
WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(activity.getWindow().getDecorView());
//Enjoy your keyboard height
int keyboardHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;
你也可以轻松监听键盘的显示/隐藏事件:
你也可以轻松监听键盘的显示/隐藏事件:
ViewCompat.setOnApplyWindowInsetsListener(activity.getWindow().getDecorView(), (v, insets) -> {
boolean isKeyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime());
int keyboardHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;
//Do your job here
return insets;
});
在这里阅读更多。
WindowCompat.setDecorFitsSystemWindows(window, false)
。无论如何,您可以通过获取顶部和底部插图的组合高度来验证键盘高度:Insets.getInsets(WindowInsets.Type.navigationBars()).bottom
。还有其他 WindowInsets.Type
的选项。 - zuko这种方法适用于你的活动中的adjustNothing
或任何windowSoftInputMode
。
<activity android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/AppTheme"
android:windowSoftInputMode="stateHidden|adjustNothing"/>
PopupWindow
,您可以为其单独设置“键盘行为”,并且它将通知您键盘的大小。PopupWindow 的高度为屏幕高度,但宽度为 0 像素,因此您看不到它,它也不会影响您的活动,但会提供您所需的信息。KeyboardHeightProvider
的类并添加以下代码:public class KeyboardHeightProvider extends PopupWindow {
public KeyboardHeightProvider(Context context, WindowManager windowManager, View parentView, KeyboardHeightListener listener) {
super(context);
LinearLayout popupView = new LinearLayout(context);
popupView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
popupView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
DisplayMetrics metrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(metrics);
Rect rect = new Rect();
popupView.getWindowVisibleDisplayFrame(rect);
int keyboardHeight = metrics.heightPixels - (rect.bottom - rect.top);
int resourceID = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceID > 0) {
keyboardHeight -= context.getResources().getDimensionPixelSize(resourceID);
}
if (keyboardHeight < 100) {
keyboardHeight = 0;
}
boolean isLandscape = metrics.widthPixels > metrics.heightPixels;
boolean keyboardOpen = keyboardHeight > 0;
if (listener != null) {
listener.onKeyboardHeightChanged(keyboardHeight, keyboardOpen, isLandscape);
}
});
setContentView(popupView);
setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
setWidth(0);
setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
setBackgroundDrawable(new ColorDrawable(0));
parentView.post(() -> showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0));
}
public interface KeyboardHeightListener {
void onKeyboardHeightChanged(int keyboardHeight, boolean keyboardOpen, boolean isLandscape);
}
}
请注意PopupWindow有自己的setSoftInputMode(...)
,因此无论您设置活动内容如何,PopupWindow仍会受到键盘打开或关闭的影响,并提供父活动的高度。如果高度>= 100
,则可以假定键盘已打开。
要使用它,请在您的Activity的onCreate(...)
方法中的setContentView(...)
之后实例化它:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
LinearLayout llRoot = findViewById(R.id.llRoot); //The root layout (Linear, Relative, Contraint, etc...)
new KeyboardHeightProvider(this, getWindowManager(), llRoot, new KeyboardHeightProvider.KeyboardHeightListener() {
@Override
public void onKeyboardHeightChanged(int keyboardHeight, boolean keyboardOpen, boolean isLandscape) {
Log.i("keyboard listener", "keyboardHeight: " + keyboardHeight + " keyboardOpen: " + keyboardOpen + " isLandscape: " + isLandscape);
//Do what you want or have to with the parameters..
}
});
//...
}
Activity
的onPause
方法中调用PopupWindow
的dismiss
方法来解决了这个问题。 - tagy22android:layout_alignParentBottom="true"
在清单文件中,将软输入法设置为adjustresize
android:windowSoftInputMode="adjustResize"
adjustResize
输入模式。
https://github.com/Crysis21/KeyboardHeightProvider
getWindow().getDecorView()
.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
@Override
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
mKeyboardShowing =
insets.getInsets(WindowInsets.Type.ime()).bottom > 0;
if (mKeyboardShowing) {
setKeyboardHeight(
insets.getInsets(WindowInsets.Type.ime()).bottom -
insets.getInsets(WindowInsets.Type.navigationBars()).bottom);
}
} else {
mKeyboardShowing = getNavigationBarHeight() !=
insets.getSystemWindowInsetBottom();
if (mKeyboardShowing) {
setKeyboardHeight(insets.getSystemWindowInsetBottom() -
getNavigationBarHeight());
}
}
return v.onApplyWindowInsets(insets);
}
public int getNavigationBarHeight() {
boolean hasMenuKey = ViewConfiguration.get(MainActivity.this)
.hasPermanentMenuKey();
int resourceId = getResources().getIdentifier("navigation_bar_height",
"dimen",
"android");
if (resourceId > 0 && !hasMenuKey) {
return getResources().getDimensionPixelSize(resourceId);
}
return 0;
}
});
navigation_bar_height
没有公开的方法,并且不能保证在所有类型的设备上都能正常工作。 - AndroidEngineX我已经在Android中使用了这个方法来动态获取键盘高度并进行测试,请尝试一下:
myLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// TODO Auto-generated method stub
Rect r = new Rect();
parent.getWindowVisibleDisplayFrame(r);
int screenHeight = parent.getRootView().getHeight();
int heightDifference = screenHeight - (r.bottom - r.top);
Log.d("Keyboard Size", "Size: " + heightDifference);
//boolean visible = heightDiff > screenHeight / 3;
}
});
OnGlobalLayoutListener
。 - Adib Faramarzi