我想根据是否显示虚拟键盘来改变布局。我已经搜索了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
}
}
}
其他回答
尽管本页上投票最多的解决方案说,有一个setWindowInsetsAnimationCallback的ViewCompat版本一直工作到Android 21。
所以现在,这个解决方案的方法一直适用于21。
来源:https://developer.android.com/reference/androidx/core/view/ViewCompat setWindowInsetsAnimationCallback (android.view.View androidx.core.view.WindowInsetsAnimationCompat.Callback)
你也可以检查第一个DecorView的子底部填充。当键盘显示时,它将被设置为非零值。
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
View view = getRootView();
if (view != null && (view = ((ViewGroup) view).getChildAt(0)) != null) {
setKeyboardVisible(view.getPaddingBottom() > 0);
}
super.onLayout(changed, left, top, right, bottom);
}
就像@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。
这可能不是最有效的解决方案。但这对我每次都有效……我调用这个函数每当我需要听软键盘。
boolean isOpened = false;
public void setListenerToRootView() {
final View activityRootView = getWindow().getDecorView().findViewById(android.R.id.content);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > 100) { // 99% of the time the height diff will be due to a keyboard.
Toast.makeText(getApplicationContext(), "Gotcha!!! softKeyboardup", 0).show();
if (isOpened == false) {
//Do two things, make the view top visible and the editText smaller
}
isOpened = true;
} else if (isOpened == true) {
Toast.makeText(getApplicationContext(), "softkeyborad Down!!!", 0).show();
isOpened = false;
}
}
});
}
注意: 如果用户使用浮动键盘,这种方法将导致问题。
隐藏|显示事件键盘可以通过简单的hack在OnGlobalLayoutListener监听:
final View activityRootView = findViewById(R.id.top_root);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > 100) {
// keyboard is up
} else {
// keyboard is down
}
}
});
这里activityRootView是Activity的根视图。