软键盘操作是Android开发中必不可少的部分,其中有一个体验是我们Android程序员必须要去优化的:
登录、注册、聊天页面,当用户点击EditText以外的控件,键盘能自动隐藏
软键盘隐藏的实现,很简单:
先分析下 EditText 因为获取焦点而弹出了软键盘,那我把 EditText 的焦点 clear,会不会隐藏软键盘呢?
其实这样是没有任何效果的,因为当你把焦点落在 EditText 中以后,点击其他区域都没有能力夺走 EditText 的焦点。必须在layout文件的根控件中加入android:clickable="true"
和
android:focusableInTouchMode="true"
然后就可以 clear 掉 EditText 的焦点并隐藏软键盘。但是这样复用性很差,如果其他页面也要实现相同的功能,那么我们只能重复一遍这样的操作。
继续思考:需求是实现EditText之外控件的 touch 事件,我们给界面中所有EditText之外控件的添加touch事件,在事件中去做hideSoftInput,这么做好像也能实现。但是这样很不优雅,又变的毫无复用性,而且代码阅读性更差了。我们自然想到 for 循环去做 setOnTouchListener,先找到根控件 rootView,然后递归给子控件setOnTouchListener。
为什么不用setOnClickListener?因为又要给每个空间添加 android_clickable=”true” 和
android:focusableInTouchMode=”true”
这么写能实现我们的需求,也能复用,把 setTouchListener 写在 BaseActivity 中。但是看得出来,很别扭,为每个控件添加 setOnTouchListener,显然不够优雅。
继续思考,有没有一个事件,能监听界面中所有触摸事件?自然就想到事件传递机制,点击 Activity 最先触发的就是 dispatchTouchEvent ,在这个事件我们判断当前焦点是不是落在 EditText 控件中,如果是那么就不隐藏软键盘,反之亦然。代码:
研究到这里其实已经解决了90%,还有10%那就是体验部分:比如聊天页面,我在 EditText 输完信息点击发送,其实是不能隐藏软键盘的,因为此时用户的状态是持续聊天中,用户不想聊天就会去关闭软键盘,所以我们要把关闭软键盘(或者说用户不想文字聊天了,改发送图片?改发语音?)的权力交给用户。
所以我们要在上面的代码中加点逻辑:过滤部分控件不会触发隐藏软键盘。
getNotHideViews 方法就不具体写了,就是你想要不做响应的控件添加进去就可以了。
最后在整理一下,为了复用性我们可以把 dispatchTouchEvent,isShouldHideInput,getNotHideViews 都放到BaseActivity中。isShouldHideInput,isShouldNotHideInput 可以用 private ,getNotHideViews 可以用 public ,让子类去实现具体有哪些view。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!