在Android中,有没有一种方法可以检测软键盘是否显示在屏幕上?
在Android中,有没有一种方法可以检测软键盘是否显示在屏幕上?
现在基于 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 }
androidx.core:core-ktx:1.9.0
。 - anhtuannd终于在2023年,官方现在提供了对此的支持!
要检查键盘是否可见,请执行以下操作:
val insets = ViewCompat.getRootWindowInsets(view) ?: return
val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
要监听键盘可见性的变化,请执行以下操作:
ViewCompat.setOnApplyWindowInsetsListener(view) { _, insets ->
val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
insets
}
android:windowSoftInputMode="adjustResize"
设置为活动。”WindowCompat.setDecorFitsSystemWindows(window, false)
启用了边缘到边缘功能时,这才有效。然而,这会导致状态栏和导航栏重叠在您的布局上。解决这个问题的快速方法是将您的布局包装在一个FrameLayout
中,并为您的布局的原始根视图设置android:fitsSystemWindows="true"
。 - undefinedpublic 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;
}
默认情况下,mKeyboardStatus的基本布尔值将初始化为false。
然后按以下方式检查该值,并在必要时执行操作:
mSearchBox.requestFocus();
if(!isKeyboardActive()){
showKeyboard();
}else{
dismissKeyboard();
}
如果您需要检查键盘状态,则应该可以使用以下方法:
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() 是将 dp 转换为 px 的 Anko 函数时:
fun dip(value: Int): Int {
return (value * Resources.getSystem().displayMetrics.density).toInt()
}
adb shell dumpsys window InputMethod | grep "mHasSurface"
试试这段代码,如果键盘已经弹出,则此函数将返回true值。
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;
}
private fun isKeyboardVisible(rootView: View) =
ViewCompat.getRootWindowInsets(rootView)!!.isVisible(WindowInsetsCompat.Type.ime())
如您所知,Android软键盘只会在有可能进行输入的事件发生时才会显示。换句话说,只有当EditText获得焦点时,键盘才会显示出来。这意味着您可以通过使用OnFocusChangeListener来判断键盘是否可见。
//Declare this Globally
public boolean isKeyBoardVisible = false;
//In OnCreate *[For Activity]*, OnCreateView *[For Fragment]*
text_send.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus)
isKeyBoardVisible = true;
else
isKeyBoardVisible = false;
}
});
现在您可以在类的任何地方使用isKeyBoardVisible变量来获取键盘是否打开。这对我很有效。
注意:当使用InputMethodManager以编程方式打开键盘时,此过程不起作用,因为它不会调用OnFocusChangeListener。
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
}
}
});
感谢大家的回答,我根据自己的情况找到了答案。
/**
* Add global layout listener to observe system keyboard visibility
*/
private void initObserverForSystemKeyboardVisibility() {
getRootView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//Add your own code here
Log.d("TEST_CODE", "isSystemKeyboardVisible:" + isSystemKeyboardVisible())
}
});
}
/**
* Check system keyboard visibility
* @return true if visible
*/
public boolean isSystemKeyboardVisible() {
try {
final InputMethodManager manager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
final Method windowHeightMethod = InputMethodManager.class.getMethod("getInputMethodWindowVisibleHeight");
final int height = (int) windowHeightMethod.invoke(manager);
return height > 0;
} catch (Exception e) {
return false;
}
}
getInputMethodWindowVisibleHeight
方法被阻止,因为使用了非 SDK API 列表。您不能在生产中使用此反射。请在此处查看更多信息:https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces - RufusInZen
executeShellCommand()
来检测键盘是否显示在屏幕上:https://stackoverflow.com/questions/33970956/test-if-soft-keyboard-is-visible-using-espresso#53118977 - undefined