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


当前回答

你可以在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)

这对我很管用。

其他回答

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

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

我用这个作为基础:https://rogerkeays.com/how-to-check-if-the-software-keyboard-is-shown-in-android

/**
* To capture the result of IMM hide/show soft keyboard
*/
public class IMMResult extends ResultReceiver {
     public int result = -1;
     public IMMResult() {
         super(null);
}

@Override 
public void onReceiveResult(int r, Bundle data) {
    result = r;
}

// poll result value for up to 500 milliseconds
public int getResult() {
    try {
        int sleep = 0;
        while (result == -1 && sleep < 500) {
            Thread.sleep(100);
            sleep += 100;
        }
    } catch (InterruptedException e) {
        Log.e("IMMResult", e.getMessage());
    }
    return result;
}
}

然后写了这个方法:

public boolean isSoftKeyboardShown(InputMethodManager imm, View v) {
    
    IMMResult result = new IMMResult();
    int res;
    
    imm.showSoftInput(v, 0, result);

    // if keyboard doesn't change, handle the keypress
    res = result.getResult();
    if (res == InputMethodManager.RESULT_UNCHANGED_SHOWN ||
            res == InputMethodManager.RESULT_UNCHANGED_HIDDEN) {

        return true;
    }
    else
        return false;

}

然后你可以用它来测试所有可能打开软键盘的字段(EditText, AutoCompleteTextView等):

    InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
    if(isSoftKeyboardShown(imm, editText1) | isSoftKeyboardShown(imm, autocompletetextview1))
        //close the softkeyboard
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

当然不是一个理想的解决方案,但它可以完成工作。

在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();
        }
    }
}
private fun isKeyboardVisible(rootView: View) =
    ViewCompat.getRootWindowInsets(rootView)!!.isVisible(WindowInsetsCompat.Type.ime())

试试这段代码,它真的工作,如果keyboardshow是显示的,那么这个函数返回真值....

private final String TAG = "TextEditor";
private TextView mTextEditor;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_editor);
    mTextEditor = (TextView) findViewById(R.id.text_editor);
    mTextEditor.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            isKeyboardShown(mTextEditor.getRootView());
        }
    });
}

private boolean isKeyboardShown(View rootView) {
    /* 128dp = 32dp * 4, minimum button height 32dp and generic 4 rows soft keyboard */
    final int SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD = 128;

    Rect r = new Rect();
    rootView.getWindowVisibleDisplayFrame(r);
    DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
    /* heightDiff = rootView height - status bar height (r.top) - visible frame height (r.bottom - r.top) */
    int heightDiff = rootView.getBottom() - r.bottom;
    /* Threshold size: dp to pixels, multiply with display density */
    boolean isKeyboardShown = heightDiff > SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD * dm.density;

    Log.d(TAG, "isKeyboardShown ? " + isKeyboardShown + ", heightDiff:" + heightDiff + ", density:" + dm.density
            + "root view height:" + rootView.getHeight() + ", rect:" + r);

    return isKeyboardShown;
}