我需要做一件非常简单的事情-找出软件键盘是否显示。这在Android中可行吗?
当前回答
希望这能帮助到大家。
Reuben Scratton给出的新答案非常棒,而且非常有效,但它只在你将windowSoftInputMode设置为adjuststresize时才有效。如果你将它设置为adjustPan,使用他的代码片段仍然无法检测键盘是否可见。为了解决这个问题,我对上面的代码做了微小的修改。
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - r.height();
if (heightDiff > 0.25*activityRootView.getRootView().getHeight()) { // if more than 25% of the screen, its probably a keyboard...
... do something here
}
}
});
其他回答
而不是假设差异编码,我做了这样的事情,因为我在我的应用程序中有菜单选项。
final View root= findViewById(R.id.myrootview);
root.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = root.getRootView().getHeight() - root.getHeight();
Rect rectgle= new Rect();
Window window= getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
int contentViewTop=
window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
if(heightDiff <= contentViewTop){
//Soft KeyBoard Hidden
}else{
//Soft KeyBoard Shown
}
}
});
这可能不适合生产环境,因为它会打开键盘。注意,类似函数返回的布尔值在API中没有指定,因此是不可靠的。参考这里的文档…
https://developer.android.com/reference/android/view/inputmethod/InputMethodManager showSoftInput (% 20 int, android.view.View % 20 android.os.resultreceiver)
public boolean showSoftInput (View view,
int flags,
ResultReceiver resultReceiver)
注意,这个方法接受一个ResultReceiver。它可以得到结果:result_unchanged_shows, RESULT_UNCHANGED_HIDDEN, result_shows,或RESULT_HIDDEN。如果得到result_unchanged_show,则键盘是可见的。如果你需要它保持关闭如果它已经关闭了,你需要关闭它。
除了正确的答案,我必须在onCreateView的末尾添加这个,当使用一个片段内的webview。
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
可能是因为我在一个片段中运行Webview,或者可能是API 30上的一个新行为,我的问题是,即使显示键盘,片段的高度也从未改变。
所以对于Fragment,整个代码应该是
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
//mWebView.postUrl("https://www.google.com/");
final View activityRootView = view;
layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
// This variable was created only for Debug purposes and
// to see the height change when clicking on a field inside mWebView
int screenHeight = activityRootView.getRootView().getHeight();
Log.d("onGlobalLayout", "rect: " + r.toString());
Log.d("onGlobalLayout", "screenHeight: " + screenHeight);
//The difference on the heights from bottom to top and on the root height
int heightDiff = screenHeight - (r.bottom - r.top);
Log.d("onGlobalLayout", "heightDiff: " + heightDiff);
//I suggest to put 250 on resources to have better order
float dpx = dpToPx(getActivity(), 250);
if (previousHeightDiff != heightDiff) {
if (heightDiff > dpx) {
isSoftKeyboardPresent = true;
} else {
isSoftKeyboardPresent = false;
}
previousHeightDiff = heightDiff;
}
}
};
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
return view;
}
private static float dpToPx(Context context, float valueInDp) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
}
检查元素的高度是不可靠的,因为一些键盘,如WifiKeyboard的高度为零。
相反,您可以使用showSoftInput()和hideSoftInput()的回调结果来检查键盘的状态。完整的细节和示例代码在
https://rogerkeays.com/how-to-check-if-the-software-keyboard-is-shown-in-android
在使用上述大多数建议添加固定数字的解决方案时,我刚刚遇到了一个错误。
S4的dpi很高,导致导航栏的高度为100px,因此我的应用程序认为键盘一直是打开的。
所以,随着所有新的高分辨率手机的发布,我认为使用硬编码值从长远来看不是一个好主意。
在各种屏幕和设备上进行测试后,我发现一个更好的方法是使用百分比。 获取decorView和你的应用内容之间的差异,然后检查这个差异的百分比。 从我得到的统计数据来看,大多数导航栏(无论大小、分辨率等)将占据屏幕的3%到5%。如果键盘是打开的,它会占据屏幕的47%到55%。
作为结论,我的解决方案是检查是否差异超过10%,然后我假设它的键盘打开。
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 碎片中的onCreateOptionsMenu
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- DSL元素android.dataBinding。enabled'已过时,已被'android.buildFeatures.dataBinding'取代
- ConstraintLayout:以编程方式更改约束
- PANIC: AVD系统路径损坏。检查ANDROID_SDK_ROOT值
- 如何生成字符串类型的buildConfigField
- Recyclerview不调用onCreateViewHolder
- Android API 21工具栏填充
- Android L中不支持操作栏导航模式
- 如何在TextView中添加一个子弹符号?
- PreferenceManager getDefaultSharedPreferences在Android Q中已弃用
- 在Android Studio中创建aar文件