我需要做一件非常简单的事情-找出软件键盘是否显示。这在Android中可行吗?
当前回答
在使用上述大多数建议添加固定数字的解决方案时,我刚刚遇到了一个错误。
S4的dpi很高,导致导航栏的高度为100px,因此我的应用程序认为键盘一直是打开的。
所以,随着所有新的高分辨率手机的发布,我认为使用硬编码值从长远来看不是一个好主意。
在各种屏幕和设备上进行测试后,我发现一个更好的方法是使用百分比。 获取decorView和你的应用内容之间的差异,然后检查这个差异的百分比。 从我得到的统计数据来看,大多数导航栏(无论大小、分辨率等)将占据屏幕的3%到5%。如果键盘是打开的,它会占据屏幕的47%到55%。
作为结论,我的解决方案是检查是否差异超过10%,然后我假设它的键盘打开。
其他回答
你可以使用InputMethodManager。isActive方法,如果键盘可见则返回true:
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.isActive();
你也可以看到键盘在一个特定的视图中是否处于活动状态:
imm.isActive(View v);
检查元素的高度是不可靠的,因为一些键盘,如WifiKeyboard的高度为零。
相反,您可以使用showSoftInput()和hideSoftInput()的回调结果来检查键盘的状态。完整的细节和示例代码在
https://rogerkeays.com/how-to-check-if-the-software-keyboard-is-shown-in-android
参考@TacB0sS的回答,我在Kotlin中开发了一个类。希望这对你有所帮助。如果需要改进,请告诉我。
class KeyboardVisibilityObserver(val layRootContainer: View?, val keyboardVisibilityListener: KeyboardVisibilityListener?) {
var isKeyboardOpen = false
private set
private var keyBoardObserver = object : ViewTreeObserver.OnGlobalLayoutListener {
private val DefaultKeyboardDP = 100
// Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff
private val EstimatedKeyboardDP = DefaultKeyboardDP + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 48 else 0
private val r = Rect()
override fun onGlobalLayout() {
if (layRootContainer != null) {
// Convert the dp to pixels.
val estimatedKeyboardHeight = TypedValue
.applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP.toFloat(), layRootContainer.resources.displayMetrics).toInt()
// Conclude whether the keyboard is shown or not.
layRootContainer.getWindowVisibleDisplayFrame(r)
val heightDiff = layRootContainer.rootView.height - (r.bottom - r.top)
val isShown = heightDiff >= estimatedKeyboardHeight
if (isShown == isKeyboardOpen) {
// Log.d("Keyboard state", "Ignoring global layout change...");
return
}
isKeyboardOpen = isShown
keyboardVisibilityListener?.onKeyboardVisibilityChanged(isKeyboardOpen)
}
}
}
init {
layRootContainer?.viewTreeObserver?.addOnGlobalLayoutListener(keyBoardObserver)
}
// call this in onDestroy
fun removeObserver(){
layRootContainer?.viewTreeObserver?.removeOnGlobalLayoutListener(keyBoardObserver)
}
interface KeyboardVisibilityListener {
fun onKeyboardVisibilityChanged(isKeyboardOpen: Boolean)
}
}
当在viewpager中改变片段的方向时,我很难保持键盘状态。我不知道为什么,但它似乎是不稳定的,行为不同于标准的活动。
在这种情况下,要保持键盘状态,首先你应该添加android:windowSoftInputMode = "stateUnchanged"到你的AndroidManifest.xml。不过,您可能会注意到,这实际上并没有解决整个问题——如果在方向改变之前打开了键盘,那么键盘就不会为我打开。在其他所有情况下,这种行为似乎都是正确的。
然后,我们需要实现这里提到的解决方案之一。 我发现的最干净的一个是George Maisuradze的——使用hideSoftInputFromWindow中的布尔回调:
InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
return imm.hideSoftInputFromWindow(mViewPager.getWindowToken(), 0);
我将这个值存储在我的Fragment的onSaveInstanceState方法中,并在onCreate中检索它。然后,我强制显示键盘在onCreateView,如果它有一个值为真(它返回真,如果键盘是可见的,实际上隐藏它之前的片段销毁)。
医生说… https://developer.android.com/reference/androidx/core/view/WindowInsetsCompat
检查放行说明.. https://developer.android.com/jetpack/androidx/releases/core#1.5.0-alpha02
要获得当前键盘可见性,可以使用getRootWindowInsets,然后调用isVisible()函数,传入IME类型。
val windowinsetscompat = ViewCompat.getRootWindowInsets(view)
val imeVisible = windowinsetscompat.isVisible(Type.ime())
也有监听OnApplyWindowInsetsListener的变化
ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets ->
val imeVisible = insets.isVisible(Type.ime())
}
推荐文章
- 警告: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文件