如何检测软件键盘在Android设备上是否可见?

and*_*eea 221 keyboard android

Android中是否有办法检测屏幕上是否显示软件(又称"软")键盘?

Bro*_*Han 257

这适合我.也许这始终是所有版本的最佳方式.

由于onGlobalLayout方法多次调用,因此创建键盘可见性属性并延迟观察此更改将是有效的.还要检查设备旋转.

boolean isKeyboardShowing = false;
void onKeyboardVisibilityChanged(boolean opened) {
    print("keyboard " + opened);
}

// ContentView is the root view of the layout of this activity/fragment    
contentView.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {

        Rect r = new Rect();
        contentView.getWindowVisibleDisplayFrame(r);
        int screenHeight = contentView.getRootView().getHeight();

        // r.bottom is the position above soft keypad or device button.
        // if keypad is shown, the r.bottom is smaller than that before.
        int keypadHeight = screenHeight - r.bottom;

        Log.d(TAG, "keypadHeight = " + keypadHeight);

        if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
            // keyboard is opened
            if (!isKeyboardShowing) {
                isKeyboardShowing = true
                onKeyboardVisibilityChanged(true)
            }
        }
        else {
            // keyboard is closed
            if (isKeyboardShowing) {
                isKeyboardShowing = false
                onKeyboardVisibilityChanged(false)
            }
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 这是一个工作要点:https://gist.github.com/faruktoptas/e9778e1f718214938b00c2dcd2bed109 (3认同)
  • 唯一适用于Android 6的东西.谢谢. (2认同)
  • 在哪里声明“ contentView”? (2认同)

IHe*_*oid 68

试试这个:

InputMethodManager imm = (InputMethodManager) getActivity()
            .getSystemService(Context.INPUT_METHOD_SERVICE);

    if (imm.isAcceptingText()) {
        writeToLog("Software Keyboard was shown");
    } else {
        writeToLog("Software Keyboard was not shown");
    }
Run Code Online (Sandbox Code Playgroud)

  • 在这方面,Android框架缺乏,更糟糕的是,*不一致*是可悲的*.这应该是超级简单的. (161认同)
  • 它总是回归真实. (27认同)
  • 这对我不起作用.即使在键盘从未显示或显示然后关闭的情况下,键盘显示分支也会触发. (8认同)
  • 这显然是行不通的,因为它不是监听软键盘行为的监听器。 (3认同)

小智 65

没有直接的方法 - 请参阅http://groups.google.com/group/android-platform/browse_thread/thread/1728f26f2334c060/5e4910f0d9eb898a,其中来自Android团队的Dianne Hackborn已回复.但是,您可以通过检查#onMeasure中窗口大小是否更改来间接检测它.请参阅如何检查Android中软件键盘的可见性?.

  • 当用户执行分屏应用程序时,这实际上会中断。 (5认同)

rav*_*024 51

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

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


Com*_*ode 22

很容易

1.将id放在根视图上

rootView在这种情况下,只是一个指向我的根视图的视图relative layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/addresses_confirm_root_view"
                android:background="@color/WHITE_CLR">
Run Code Online (Sandbox Code Playgroud)

2.在您的活动中初始化您的根视图:

RelativeLayout rootView = (RelativeLayout) findViewById(R.id.addresses_confirm_root_view);

3.使用检测键盘是否打开或关闭 getViewTreeObserver()

    rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int heightDiff = rootView.getRootView().getHeight() - rootView.getHeight();

                if (heightDiff > 100) { 
                    Log.e("MyActivity", "keyboard opened");
                } else { 
                    Log.e("MyActivity", "keyboard closed");
                }
            }
        });
Run Code Online (Sandbox Code Playgroud)

  • 嘿伙伴,你能告诉我这个神奇的100来自哪里吗?为什么不是101或99?谢谢 (13认同)
  • 如果您的布局涉及底页,这将没有帮助。无法区分键盘和底板。 (3认同)
  • 它不适用于Dialog Fragment (2认同)
  • 神奇的数字取决于您的顶栏布局等。所以它与你的应用程序相关。我的一台用了400。 (2认同)

use*_*158 22

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

引自reddit 评论

val View.keyboardIsVisible: Boolean
    get() = WindowInsetsCompat
        .toWindowInsetsCompat(rootWindowInsets)
        .isVisible(WindowInsetsCompat.Type.ime())
Run Code Online (Sandbox Code Playgroud)

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

新功能

WindowInsetsCompatAPI 已更新为 Android 11 平台中的API。这包括新的ime()inset 类型,它允许检查屏幕键盘的可见性和大小。

关于ime()类型的一些警告,当您的 Activity 使用adjustResize窗口软输入模式时,它在 API 23+ 上非常可靠地工作。如果您改为使用该adjustPan模式,它应该可以可靠地返回到 API 14。

参考

  • 我必须将“WindowInsetsCompat.toWindowInsetsCompat(rootWindowInsets)”替换为“ViewCompat.getRootWindowInsets(this)”才能使其正常工作。在 Android 视频中找到它:https://youtu.be/acC7SR1EXsI?t=319 (6认同)

The*_*rer 12

所以在使用 AccessibilityServices、窗口插入、屏幕高度检测等很长时间之后,我想我找到了一种方法来做到这一点。

免责声明:它在 Android 中使用了隐藏方法,这意味着它可能不一致。但是,在我的测试中,它似乎有效。

该方法是InputMethodManager#getInputMethodWindowVisibleHeight(),它从 Lollipop (5.0) 开始就存在了。

调用返回当前键盘的高度(以像素为单位)。理论上,键盘不应该是 0 像素高,所以我做了一个简单的高度检查(在 Kotlin 中):

val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
if (imm.inputMethodWindowVisibleHeight > 0) {
    //keyboard is shown
else {
    //keyboard is hidden
}
Run Code Online (Sandbox Code Playgroud)

当我调用隐藏方法时,我使用Android Hidden API来避免反射(我为我开发的应用程序做了很多事情,这些应用程序主要是 hacky/tuner 应用程序),但这也应该可以通过反射实现:

val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
val windowHeightMethod = InputMethodManager::class.java.getMethod("getInputMethodWindowVisibleHeight")
val height = windowHeightMethod.invoke(imm) as Int
//use the height val in your logic
Run Code Online (Sandbox Code Playgroud)

  • 反射的惊人运用 (2认同)

小智 11

您可以使用androidx.core (版本 1.5.0-rc01)中的WindowInsetsCompat。此代码适用于API 21及更高版本。Kotlin 代码示例:

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

root是您的 Activity 的根视图。

更新

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

  1. 添加android:windowSoftInputMode="adjustResize"到我的 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"
          />
Run Code Online (Sandbox Code Playgroud)
  1. 在您的活动中, set WindowCompat.setDecorFitsSystemWindows(window, false),这告诉 android 我们想要手动处理事情/不想使用系统默认值:
ViewCompat.setOnApplyWindowInsetsListener(root) { v, insets ->
    val isKeyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
    if (isKeyboardVisible) {
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 最后,设置你onApplyWindowInsetsListener
xml
        <activity android:name="com.soumicslabs.activitykt.StartActivity"
            android:theme="@style/AccountKitTheme.Default"
          android:configChanges="orientation|screenSize"
          android:screenOrientation="portrait"
          android:windowSoftInputMode="adjustResize"
          />
Run Code Online (Sandbox Code Playgroud)

这对我有用。


小智 10

2023 年终于有了官方支持!

这是文档

要检查键盘是否可见,请执行以下操作:

val insets = ViewCompat.getRootWindowInsets(view) ?: return
val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
Run Code Online (Sandbox Code Playgroud)

要监听键盘可见性的变化,请执行以下操作:

ViewCompat.setOnApplyWindowInsetsListener(view) { _, insets ->
  val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
  val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
  insets
}
Run Code Online (Sandbox Code Playgroud)

注意:Google 建议您将应用程序配置为边对边显示,以便其正常工作。他们还说“为了实现与此 AndroidX 实现的最佳向后兼容性,请设置android:windowSoftInputMode="adjustResize"为 AndroidManifest.xml 中的活动。”


Chr*_*ckl 7

我以此为基础:http://www.ninthavenue.com.au/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;
}
}
Run Code Online (Sandbox Code Playgroud)

然后写了这个方法:

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;

}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用它来测试可能已打开软键盘的所有字段(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);
Run Code Online (Sandbox Code Playgroud)

Addmittely不是一个理想的解决方案,但它完成了工作.

  • 这可行。如果您实现为singelton,则可以将所有焦点焦点更改应用到编辑文本,并拥有一个全局键盘监听器 (2认同)

Bha*_*har 7

现在终于有一个直接从基于Kotlin的Android R开始的方法了。

 val imeInsets = requireView().rootWindowInsets.isVisible(WindowsInsetsCompat.Type.ime()) 
    if (imeInsets) { 
     //Ime is visible
     //Lets move our view by the height of the IME
     view.translationX = imeInsets.bottom }
Run Code Online (Sandbox Code Playgroud)


Rog*_*ays 6

您可以使用showSoftInput()和hideSoftInput()的回调结果来检查键盘的状态.完整的详细信息和示例代码

http://www.ninthavenue.com.au/how-to-check-if-the-software-keyboard-is-shown-in-android


Fut*_*oof 6

对于我需要的要求,这要简单得多。希望这可能会有所帮助:

在 MainActivity 上:

public void dismissKeyboard(){
    InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(mSearchBox.getWindowToken(), 0);
    mKeyboardStatus = false;
}

public void showKeyboard(){
    InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
    mKeyboardStatus = true;
}

private boolean isKeyboardActive(){
    return mKeyboardStatus;
}
Run Code Online (Sandbox Code Playgroud)

mKeyboardStatus 的默认原始布尔值将初始化为false

然后按如下方式检查值,并在必要时执行操作:

 mSearchBox.requestFocus();
    if(!isKeyboardActive()){
        showKeyboard();
    }else{
        dismissKeyboard();
    }
Run Code Online (Sandbox Code Playgroud)


l'-*_*-'l 5

你可以参考这个答案 - /sf/answers/1687354371/

它每次都适合我.

adb shell dumpsys window InputMethod | grep "mHasSurface"
Run Code Online (Sandbox Code Playgroud)

如果软键盘可见,它将返回true.

  • 这仅在开发期间有用 - 而不是在应用程序中使用的解决方案.(用户不会运行adb.) (7认同)

Boh*_*nyk 5

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

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);
}
Run Code Online (Sandbox Code Playgroud)

其中UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP= 100 和 dip() 是一个转换 dpToPx 的 anko 函数:

fun dip(value: Int): Int {
    return (value * Resources.getSystem().displayMetrics.density).toInt()
}
Run Code Online (Sandbox Code Playgroud)

  • Спасибо!Ты спас мое время =) (2认同)

归档时间:

查看次数:

242498 次

最近记录:

5 年,12 月 前