我想根据是否显示虚拟键盘来改变布局。我已经搜索了API和各种博客,但似乎找不到任何有用的东西。
这可能吗?
谢谢!
我想根据是否显示虚拟键盘来改变布局。我已经搜索了API和各种博客,但似乎找不到任何有用的东西。
这可能吗?
谢谢!
当前回答
以上@Filipkowicz的答案在Android API < 30的情况下很好。由于Android API 30,我们应该使用setWindowInsetsAnimationCallback。所以下面的答案结合了这两种方法,以工作API 21 - 30。
private fun isKeyboardVisible(insets: WindowInsets): Boolean {
val insetsCompat = WindowInsetsCompat.toWindowInsetsCompat(insets)
val systemWindow = insetsCompat.systemWindowInsets
val rootStable = insetsCompat.stableInsets
if (systemWindow.bottom > rootStable.bottom) {
// This handles the adjustResize case on < API 30, since
// systemWindow.bottom is probably going to be the IME
return true
}
return false
}
@JvmStatic
@BindingAdapter("goneWhenKeyboardVisible")
fun View.goneWhenKeyboardVisible() {
if (isRPlus()) {
setWindowInsetsAnimationCallback(object :
WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
override fun onProgress(
insets: WindowInsets,
runningAnimations: MutableList<WindowInsetsAnimation>
): WindowInsets {
return insets
}
override fun onStart(
animation: WindowInsetsAnimation,
bounds: WindowInsetsAnimation.Bounds
): WindowInsetsAnimation.Bounds {
if (isVisible)
isVisible = !rootWindowInsets.isVisible(WindowInsets.Type.ime())
return super.onStart(animation, bounds)
}
override fun onEnd(animation: WindowInsetsAnimation) {
super.onEnd(animation)
if (!isVisible)
isVisible = !rootWindowInsets.isVisible(WindowInsets.Type.ime())
}
})
} else {
setOnApplyWindowInsetsListener { _, insets ->
isVisible = !isKeyboardVisible(insets)
insets
}
}
}
其他回答
桑德,我相信你是想展示被软键盘挡住的视野。试试这个http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html。
尽管本页上投票最多的解决方案说,有一个setWindowInsetsAnimationCallback的ViewCompat版本一直工作到Android 21。
所以现在,这个解决方案的方法一直适用于21。
来源:https://developer.android.com/reference/androidx/core/view/ViewCompat setWindowInsetsAnimationCallback (android.view.View androidx.core.view.WindowInsetsAnimationCompat.Callback)
我解决这个问题通过覆盖onkeyprime (int keyCode, KeyEvent事件)在我的自定义EditText。
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
//keyboard will be hidden
}
}
使用viewTreeObserver轻松获取键盘事件。
layout_parent.viewTreeObserver.addOnGlobalLayoutListener {
val r = Rect()
layout_parent.getWindowVisibleDisplayFrame(r)
if (layout_parent.rootView.height - (r.bottom - r.top) > 100) { // if more than 100 pixels, its probably a keyboard...
Log.e("TAG:", "keyboard open")
} else {
Log.e("TAG:", "keyboard close")
}
}
** layout_parent是你的视图,比如edit_text.parent
就像@amalBit的答案一样,注册一个全局布局的监听器,并计算dectorView的可见底部和建议底部的差值,如果差值大于某个值(猜测IME的高度),我们认为IME是up的:
final EditText edit = (EditText) findViewById(R.id.edittext);
edit.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (keyboardShown(edit.getRootView())) {
Log.d("keyboard", "keyboard UP");
} else {
Log.d("keyboard", "keyboard Down");
}
}
});
private boolean keyboardShown(View rootView) {
final int softKeyboardHeight = 100;
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
int heightDiff = rootView.getBottom() - r.bottom;
return heightDiff > softKeyboardHeight * dm.density;
}
高度阈值100是IME猜测的最小高度。
这适用于adjustPan和adjuststresize。