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


当前回答

我创建了一个可以用于此目的的简单类:https://github.com/ravindu1024/android-keyboardlistener。只需将其复制到您的项目中,并按如下方式使用:

KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
    @Override
    public void onToggleSoftKeyboard(boolean isVisible)
    {
        Log.d("keyboard", "keyboard visible: "+isVisible);
    }
});

其他回答

@iWantScala的回答很棒,但不适合我 rootView.getRootView().getHeight()总是有相同的值

一种方法是定义两个变量

private int maxRootViewHeight = 0;
private int currentRootViewHeight = 0;

添加全局监听器

rootView.getViewTreeObserver()
    .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            currentRootViewHeight = rootView.getHeight();
            if (currentRootViewHeight > maxRootViewHeight) {
                maxRootViewHeight = currentRootViewHeight;
            }
        }
    });

然后检查

if (currentRootViewHeight >= maxRootViewHeight) {
    // Keyboard is hidden
} else {
    // Keyboard is shown
}

工作正常

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

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()
}

在Android中,你可以通过ADB shell进行检测。我写下并使用了这个方法:

{
        JSch jsch = new JSch();
        try {
            Session session = jsch.getSession("<userName>", "<IP>", 22);
            session.setPassword("<Password>");
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();

            ChannelExec channel = (ChannelExec)session.openChannel("exec");
            BufferedReader in = new BufferedReader(new    
            InputStreamReader(channel.getInputStream()));
            channel.setCommand("C:/Android/android-sdk/platform-tools/adb shell dumpsys window 
            InputMethod | findstr \"mHasSurface\"");
            channel.connect();

            String msg = null;
            String msg2 = " mHasSurface=true";

            while ((msg = in.readLine()) != null) {
                Boolean isContain = msg.contains(msg2);
                log.info(isContain);
                if (isContain){
                    log.info("Hiding keyboard...");
                    driver.hideKeyboard();
                }
                else {
                    log.info("No need to hide keyboard.");
                }
            }

            channel.disconnect();
            session.disconnect();

        } catch (JSchException | IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在我的情况下,我只有一个编辑文本来管理我的布局,所以我想出了这个解决方案。 它工作得很好,基本上它是一个自定义的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上使用WindowInsetsCompat。Core(版本1.5.0-rc01)。 此代码将从API 21及以上版本工作。Kotlin代码示例:

ViewCompat.setOnApplyWindowInsetsListener(root) { v, insets ->
    val isKeyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
    if (isKeyboardVisible) {
    }
}

root是Activity的根视图。

更新

今天我正在寻找如何检测键盘可见性。起初,这个代码不起作用。所以我不得不:

添加android:windowSoftInputMode=" adjuststresize "到我的AndroidManifest.xml文件:

xml
        <activity android:name="com.soumicslabs.activitykt.StartActivity"
            android:theme="@style/AccountKitTheme.Default"
          android:configChanges="orientation|screenSize"
          android:screenOrientation="portrait"
          android:windowSoftInputMode="adjustResize"
          />

在您的活动中,设置WindowCompat。setDecorFitsSystemWindows(window, false),这告诉android我们想手动处理的东西/不想使用系统默认值:

        val window = this.window
        WindowCompat.setDecorFitsSystemWindows(window, false)  // <-- this tells android not to use system defaults, so we have to setup quite a lot of behaviors manually

最后,设置你的onApplyWindowInsetsListener:

val callBack = OnApplyWindowInsetsListener { view, insets ->
            val imeHeight = insets?.getInsets(WindowInsetsCompat.Type.ime())?.bottom?:0
            Log.e("tag", "onKeyboardOpenOrClose imeHeight = $imeHeight")
// todo: logic
val isKeyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
    if (isKeyboardVisible) {
       // do something
    }else{
        // do something else
    }
    insets?: WindowInsetsCompat(null)
  }

ViewCompat.setOnApplyWindowInsetsListener(mainContainer, callBack)

这对我很管用。