在Android中,有没有一种方法可以检测软键盘是否显示在屏幕上?
在Android中,有没有一种方法可以检测软键盘是否显示在屏幕上?
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);
}
}
}
});
contentView
声明在哪里? - Code-Apprentice试试这个:
InputMethodManager imm = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isAcceptingText()) {
writeToLog("Software Keyboard was shown");
} else {
writeToLog("Software Keyboard was not shown");
}
我创建了一个简单的类,可用于此目的:https://github.com/ravindu1024/android-keyboardlistener。只需将其复制到您的项目中,并按以下方式使用:
KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
@Override
public void onToggleSoftKeyboard(boolean isVisible)
{
Log.d("keyboard", "keyboard visible: "+isVisible);
}
});
findViewById
,则可以完美地工作,但如果使用View Binding,则会出现错误(act.findViewById<View>(… ViewGroup).getChildAt(0) must not be null
。有什么建议吗? - Aldan没有直接的方法 - 参见 Android 团队成员 Dianne Hackborn 在 http://groups.google.com/group/android-platform/browse_thread/thread/1728f26f2334c060/5e4910f0d9eb898a 中的回复。但是,您可以通过检查 #onMeasure 中的窗口大小是否更改来间接检测它。请参见如何在 Android 上检查软件键盘的可见性?
通过androidx core release 1.5.0-alpha02中的新功能WindowInsetsCompat
,您可以轻松地检查软键盘的可见性,如下所示。
引用自reddit comment。
val View.keyboardIsVisible: Boolean
get() = WindowInsetsCompat
.toWindowInsetsCompat(rootWindowInsets)
.isVisible(WindowInsetsCompat.Type.ime())
关于向后兼容性的一些注释,引用自发布说明
新功能
WindowInsetsCompat
API已经更新为Android 11平台中的API。这包括新的ime()
插入类型,它允许检查屏幕键盘的可见性和大小。关于
ime()
类型的一些注意事项,它在API 23+上非常可靠,当您的Activity使用adjustResize
窗口软输入模式时。如果您改用adjustPan
模式,则应该能够向后兼容到API 14。
参考资料
WindowInsetsCompat.toWindowInsetsCompat(rootWindowInsets)
替换为 ViewCompat.getRootWindowInsets(this)
。在Android视频中找到了这个方法:https://youtu.be/acC7SR1EXsI?t=319 - AndrazProotView
只是一个指向我的根视图的视图,在这种情况下是一个相对布局
:
<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">
RelativeLayout rootView = (RelativeLayout) findViewById(R.id.addresses_confirm_root_view);
getViewTreeObserver()
来检测键盘是否打开或关闭: rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = rootView.getRootView().getHeight() - rootView.getHeight();
if (heightDiff > 100) { // Value should be less than keyboard's height
Log.e("MyActivity", "keyboard opened");
} else {
Log.e("MyActivity", "keyboard closed");
}
}
});
经过长时间尝试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
}
我使用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
您可以使用androidx.core(版本1.5.0-rc01)中的WindowInsetsCompat。
此代码将在API 21及以上版本上运行。Kotlin代码示例:
ViewCompat.setOnApplyWindowInsetsListener(root) { v, insets ->
val isKeyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
if (isKeyboardVisible) {
}
}
root 是你的 Activity 的根视图。
今天我在寻找如何检测键盘可见性。起初,这段代码并没有起作用。所以我不得不:
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"
/>
WindowCompat.setDecorFitsSystemWindows(window, false)
,这会告诉安卓我们想要手动处理事物/不想使用系统默认值: 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://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);
诚然,这不是一个理想的解决方案,但它可以完成工作。
executeShellCommand()
来检测键盘是否显示在屏幕上:https://stackoverflow.com/questions/33970956/test-if-soft-keyboard-is-visible-using-espresso#53118977 - undefined