Android开发中软键盘的显示和隐藏

Android开发中软键盘的显示和隐藏,第1张

概述本篇内容通过 *** 作软键盘的函数着手详细分析了隐藏或者显示软键盘的实现方法,并且对其中重要的代码做了详细分析。

本篇内容通过 *** 作软键盘的函数着手详细分析了隐藏或者显示软键盘的实现方法,并且对其中重要的代码做了详细分析。

一、开篇

如果有需要用到输入的地方,通常会有需要自动d出或者收起软键盘的需求。开篇明义,本文会讲讲d出和收起软键盘的一些细节,最终还会从源码进行分析。

想要 *** 作软键盘,需要使用到 inputMethodManager ,它是一个系统服务,可以使用 Context.getSystemService() 获取到它。而很多关键的逻辑代码,都是在 inputMethodManagerService 中实现的。

特别说明:本文的所有分析的源码,都是基于 AndroID 26 的源码。

二、 *** 作软键盘

2.1 inputMethodManager

前面提到,想要 *** 作软键盘,需要使用 inputMethodManager ,它是一个系统服务,想要获取它,可以使用 getSystemService() ,获取到它。

毕竟是系统服务,使用的时候为了安全,还是要判空,避免空指针。

2.2 显示软键盘

在 inputMethodManager 中,有两个方法 showSoftinput()showSoftinputFrominputMethod() ,而实际上,只有 showSoftinput() 是有效的。

它有两个重载方法,而通常我们会使用它的两个参数的方法。

这里我们只需要传递两个参数。它首先需要一个 VIEw ,使用软键盘就是为了输入,而输入就需要有接收输入内容的 VIEw ,这里接收输入的 VIEw ,最好是一个 EditText(但这不是必须的)。

而第二个参数 flags 就是个标志位,从上面截图的方法签名上的文档上可以看到,它接收 0 或者 SHOW_INPYT_IMPliCIT 两个参数,但是实际上,它有第三个参数,另外一个是 SHOW_FORCED。

可以看到 1、2 都是有特殊含义的,实际上它们并不影响显示,只是在隐藏的时候,会有一些限制,这些后面看源码的时候再说,一般没有特别需要的话,我们直接传递 0 就好了。

现在,简单总结一下调用 showSoftinput() 会生效的关键点:

1、第一个参数,最好是 EditText 或者它的子类。

考虑到软键盘就是为了输入,EditText 就是一个接收输入的控件。而这不是绝对的,如果不是一个 EditText ,就必须要求这个 VIEw 有两个属性,分别是:androID:focusable="true"androID:focusableIntouchMode="true"

2、第一个参数,必须是可获取焦点的,并且当前已经获取到焦点。

EditText 默认是允许获取焦点的,但是假如布局中,存在多个可获取焦点的控件,就需要提前让我们传递进去的 VIEw 获取到焦点。获取焦点可以使用 requestFocus() 方法。

3、布局必须加载完成。

onCreate() 中,如果立即调用 showSoftinput() 是不会生效的。想要在页面一启动的时候就d出键盘,可以在 Activity 上,设置 androID:windowsoftinputMode 属性来完成,或者做一个延迟加载,VIEw.postDelayed() 也是一个解决方案。

所以最终,完整的显示软键盘的代码就如下所示了。

2.3 隐藏软键盘

虽然 showSoftinput() 方法是有效的,但是想要隐藏软键盘,就没有提供对应的 hIDeSoftinput() 方法,但是却有一个 hIDeSoftinputFromWindow() 方法,可以用来隐藏软键盘。

先来看看这个方法的签名,它同样有两个方法可以调用。

它接收两个参数,第一个参数是一个 IBinder ,可以直接传递一个 VIEw.getwindowToken() 的 windowToken 对象就可以了。而第二个参数,就是隐藏软键盘的标志位,如果没有特殊要求的话,直接传递 0 就好了。

注意这里虽然原则上需要传递一个之前d出键盘传递的时候,传递的 VIEw 的 windowToken ,但是实际情况是你只需要传递一个存在于当前布局 VIEwTree 中,随意一个 VIEw 的 windowToken 就可以了。

最终隐藏软件的代码就是这样的。

2.4 切换键盘的d出和隐藏

在 inputMethodManager 中,还提供了一个 toggleSoftinput() 方法,如同它的名字一样,它可以让软键盘在显示和隐藏之间切换。

该方法,接收两个 flags ,分别是控制 show 和 hIDe 时候的标识,它们的含义和前面介绍的 showSoftinput()hIDeSoftinputFromWindow() 一致,所以没有特殊要求,直接传递 0 就好了。

toggleSoftinput() 方法不要求传递一个 VIEw 或者 windowToken,所以它并没有 showSoftinput() 中的一些限制,但是依然还有需要在布局绘制完成之后调用才会有效果。

虽然这个方法,限制很少,但是我们基本上不会使用它。主要原因在于,它是一个开关的方法,会根据当前的状态做相反的 *** 作。这就导致很多时候,我们在代码中,无法直接根据 inputMethodManager 提供的方法判断当前软键盘的显示状态,这样也就无法确定调用它的时候的效果了。

三、源码分析

3.1 flag 的细节

前面的一些方法,都需要传递一个 flag 值,文档中描述的并不详细,我们就从源码的角度,来分析一下这些 flag 的含义。

先来看看 showSoftinput() 方法。

它最终会调用 mService.showSoftinput() 方法,最终的源码,就需要查看 inputMethodManagerService 中的代码了。而 showSoftinput() 方法,最终会调用 showCurrentinputLocked()

可以看到,flag 会影响两个字段,mShowExplicitlyRequested 和 mShowForced,而 SHOW_FORCED 会更强势一点。

hIDeSoftinputFromWindow() 方法,最终也会调用 inputMethodManagerService 中的 hIDeCurrentinputLocked() 方法。

DEBUG == true 会输出的 Log 中,已经可以看到含义了。这里会根据显示和隐藏传递的两个 flag 来进行比对,也就是说,如果 flag 使用不正确,可能导致这里直接返回 false ,从而无法隐藏软键盘,这些细节对照代码就清晰了,就不在文章里屡这些细节了。

所以这就是为什么前面提到,如果没有特殊要求,直接传递 0 就好了,可以规避这个限制。

3.2 如何判断软键盘是否d出

既然 toggleSoftinput() 可以根据当前软键盘的状态,进行不同的 *** 作,那么肯定是有办法确定当前软键盘的状态的。

那我们继续追踪 toggleSoftinput() 的方法源码。

该方法,最终会调用到 inputMethodService 的 onToggleSoftinput() 方法。

在这个方法中,是根据 isinputVIEwShow() 方法来判定当前软键盘是否处于显示d出的状态。但是我们并没有办法,直接和 inputMethodService 进行交互,我们也就没办法直接拿到当前键盘是否显示。

如果想要监听键盘的d出和收起,可以使用 VIEwTreeObserver.OnGlobalLayoutListener 这个监听,来监听布局的调整,从而判断出键盘的d出和隐藏。这些细节有时间再聊。

四、KeyboardUtils

既然已经清楚了软键盘的收起和d出的方法细节,那我们来写一个帮助类,来解决这个问题。让你们拿到就可用。

这里提供一下 Java 版和 Kotlin 版。

4.1 Java 版

public class KeyboardUtils { public static voID showKeyboard(VIEw vIEw) {  inputMethodManager imm = (inputMethodManager) vIEw.getContext()    .getSystemService(Context.input_METHOD_SERVICE);  if (imm != null) {   vIEw.requestFocus();   imm.showSoftinput(vIEw,0);  } } public static voID hIDeKeyboard(VIEw vIEw){  inputMethodManager imm = (inputMethodManager) vIEw.getContext()    .getSystemService(Context.input_METHOD_SERVICE);  if (imm != null) {   imm.hIDeSoftinputFromWindow(vIEw.getwindowToken(),0);  } } public static voID toggleSoftinput(VIEw vIEw){  inputMethodManager imm = (inputMethodManager) vIEw.getContext()    .getSystemService(Context.input_METHOD_SERVICE);  if (imm != null) {   imm.toggleSoftinput(0,0);  } }}

 

4.2 Kotlin 版

object KeyboardktUtils{ fun showKeyboard(vIEw: VIEw) {  val imm = vIEw.context    .getSystemService(Context.input_METHOD_SERVICE) as inputMethodManager  if (imm != null) {   vIEw.requestFocus()   imm.showSoftinput(vIEw,0)  } } fun hIDeKeyboard(vIEw: VIEw) {  val imm = vIEw.context    .getSystemService(Context.input_METHOD_SERVICE) as inputMethodManager  imm?.hIDeSoftinputFromWindow(vIEw.windowToken,0) } fun toggleSoftinput(vIEw: VIEw) {  val imm = vIEw.context    .getSystemService(Context.input_METHOD_SERVICE) as inputMethodManager  imm?.toggleSoftinput(0,0) }}

以上就是本文的全部内容,如果大家学习了以后还有任何不明白的地方,可以在下方的留言区进行讨论。

总结

以上是内存溢出为你收集整理的Android开发中软键盘的显示和隐藏全部内容,希望文章能够帮你解决Android开发中软键盘的显示和隐藏所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1143479.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存