前一句,从本篇起始源代码的角度分析问题。
应用层的问题可以回去看看上一篇文章。三、源码分析
3.1 flag 的细节
前面的一些方法,都需要传递一个 flag 值,文档中描述的并不详细,我们就从源码的角度,来分析一下这些 flag 的含义。
先来看看 showSoftInput()
方法。
它最终会调用 mService.showSoftInput()
方法,最终的源码,就需要查看 InputMethodManagerService 中的代码了。而 showSoftInput()
方法,最终会调用 showCurrentInputLocked()
。
这个方法的代码很长,我们只关心和 flag 相关的代码。
可以看到,flag 会影响两个字段,mShowExplicitlyRequested 和 mShowForced,而 SHOW_FORCED 会更强势一点。
hideSoftInputFromWindow()
方法,最终也会调用 InputMethodManagerService 中的 hideCurrentInputLocked()
方法。
从 DEBUG == true
会输出的 Log 中,已经可以看到含义了。这里会根据显示和隐藏传递的两个 flag 来进行比对,也就是说,如果 flag 使用不正确,可能导致这里直接返回 false ,从而无法隐藏软键盘,这些细节对照代码就清晰了,就不在文章里屡这些细节了。
所以这就是为什么前面提到,如果没有特殊要求,直接传递 0 就好了,可以规避这个限制。
3.2 如何判断软键盘是否弹出
既然 toggleSoftInput()
可以根据当前软键盘的状态,进行不同的操作,那么肯定是有办法确定当前软键盘的状态的。
那我们继续追踪 toggleSoftInput()
的方法源码。
该方法,最终会调用到 InputMethodService 的 onToggleSoftInput()
方法。
在这个方法中,是根据 isInputViewShow()
方法来判定当前软键盘是否处于显示弹出的状态。但是我们并没有办法,直接和 InputMethodService 进行交互,我们也就没办法直接拿到当前键盘是否显示。
如果想要监听键盘的弹出和收起,可以使用 ViewTreeOb 这个监听,来监听布局的调整,从而判断出键盘的弹出和隐藏。这些细节有时间再聊。
四、KeyboardUtils
既然已经清楚了软键盘的收起和弹出的方法细节,那我们来写一个帮助类,来解决这个问题。让你们拿到就可用。
这里提供一下 Java 版和 kotlin 版。
4.1 Java 版
public class KeyboardUtils { public static void showKeyboard(View view) { InputMethodManager imm = (InputMethodManager) view.getContext() .getSystemService); if (imm != null) { view.requestFocus(); imm.showSoftInput(view, 0); } } public static void hideKeyboard(View view){ InputMethodManager imm = (InputMethodManager) view.getContext() .getSystemService); if (imm != null) { imm.hideSoftInputFromWindow(),0); } } public static void toggleSoftInput(View view){ InputMethodManager imm = (InputMethodManager) view.getContext() .getSystemService); if (imm != null) { imm.toggleSoftInput(0,0); } }}4.2 Kotlin 版
object KeyboardktUtils{ fun showKeyboard(view: View) { val imm = view.context .getSystemService) as InputMethodManager if (imm != null) { view.requestFocus() imm.showSoftInput(view, 0) } } fun hideKeyboard(view: View) { val imm = view.context .getSystemService) as InputMethodManager imm?.hideSoftInputFromWindow, 0) } fun toggleSoftInput(view: View) { val imm = view.context .getSystemService) as InputMethodManager imm?.toggleSoftInput(0, 0) }}我准备了一些我整理的学习资料,包含:Android反编译、算法、设计模式、kotlin、Python、爬虫、虚拟机、Linux、计算机网络、Web项目源码。如果有兴趣可以私信我。