Android系统中是否有一种方法可以检测软件(也就是Android。“软”)键盘在屏幕上可见吗?


当前回答

这应该工作,如果你需要检查键盘状态:

fun Activity.isKeyboardOpened(): Boolean {
    val r = Rect()

    val activityRoot = getActivityRoot()
    val visibleThreshold = dip(UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP)

    activityRoot.getWindowVisibleDisplayFrame(r)

    val heightDiff = activityRoot.rootView.height - r.height()

    return heightDiff > visibleThreshold;
}

fun Activity.getActivityRoot(): View {
    return (findViewById<ViewGroup>(android.R.id.content)).getChildAt(0);
}

UiUtils的地方。KEYBOARD_VISIBLE_THRESHOLD_DP = 100, dip()是一个anko函数,转换dpToPx:

fun dip(value: Int): Int {
    return (value * Resources.getSystem().displayMetrics.density).toInt()
}

其他回答

final View activityRootView = findViewById(R.id.rootlayout);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            Rect r = new Rect();
            activityRootView.getWindowVisibleDisplayFrame(r);

            int screenHeight = activityRootView.getRootView().getHeight();
            Log.e("screenHeight", String.valueOf(screenHeight));
            int heightDiff = screenHeight - (r.bottom - r.top);
            Log.e("heightDiff", String.valueOf(heightDiff));
            boolean visible = heightDiff > screenHeight / 3;
            Log.e("visible", String.valueOf(visible));
            if (visible) {
                Toast.makeText(LabRegister.this, "I am here 1", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(LabRegister.this, "I am here 2", Toast.LENGTH_SHORT).show();
            }
        }
});

在我的情况下,我只有一个编辑文本来管理我的布局,所以我想出了这个解决方案。 它工作得很好,基本上它是一个自定义的EditText,它监听焦点,并在焦点改变或按下后退/完成按钮时发送本地广播。 要工作,你需要在你的布局与android: focableintouchmode ="true"和android:focusableInTouchMode="true",因为当你调用clearFocus()的焦点将被重新分配到第一个可聚焦的视图。 虚拟视图示例:

<View
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
android:focusableInTouchMode="true"/>

额外的信息

检测布局变化差异的解决方案效果不太好,因为它强烈依赖于屏幕密度,因为100px在某些设备上可能很大,而在其他设备上可能没有,你可能会得到误报。 另外,不同的厂商有不同的键盘。

使用androidx核心版本1.5.0-alpha02中的新特性WindowInsetsCompat,您可以轻松地检查软键盘的可见性,如下所示

摘自reddit评论

瓦尔View)。布尔keyboardIsVisible: 赢了 toWindowInsetsCompat (rootWindowInsets)。 isVisible (WindowInsetsCompat。。火车(型)

一些关于向后兼容性的说明,引用自发行说明

新功能 windowswinsetscompat api已经更新为平台中的api Android 11。这包括新的ime()插入类型,它允许 检查屏幕上键盘的可见性和大小。 一些关于ime()类型的警告,它在API 23+上工作非常可靠 当你的Activity使用adjuststresize窗口软输入模式时。 如果您使用的是adjustPan模式,它应该工作可靠 回到API 14。

参考文献

Twitter WindowInsetsCompat公告 Reddit的线程 Androidx Core 1.5.0-alpha02发布说明 WindowInsetsCompat文档

private fun isKeyboardVisible(rootView: View) =
    ViewCompat.getRootWindowInsets(rootView)!!.isVisible(WindowInsetsCompat.Type.ime())

我通过设置一个GlobalLayoutListener来做到这一点,如下所示:

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
        new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int heightView = activityRootView.getHeight();
                int widthView = activityRootView.getWidth();
                if (1.0 * widthView / heightView > 3) {
                    //Make changes for Keyboard not visible
                } else {
                    //Make changes for keyboard visible
                }
            }
        });