Android之TouchMode知多少

前言:
最近在阅读View源码onTouchEvent(MotionEvent event)这个方法的时候遇到了下面这段代码:

if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {   
    focusTaken = requestFocus();
}

这段代码if里面的第一个条件和最后一个条件都好理解,偏偏这个isFocusableInTouchMode()方法没太搞明白,源码中这么解释它的。

When a view is focusable, it may not want to take focus when in touch mode.
For example, a button would like focus when the user is navigating via a D-pad
so that the user can click on it, but once the user starts touching the screen,
the button shouldn't take focus.

具体是什么意思,我也没太弄明白,所有我就去Google之。然后呢,就在 Android Developers Blog 找到了《Touch Mode》这篇文章,在这里面google对touch mode 模式进行了详尽的介绍,下面是部分译文。

Touch Mode, Selection, and Focus

<p>移动设备提供了不同的用户交互方式,譬如利用12键、触摸屏幕、手写笔或者同时利用手机键盘和触摸屏幕来进行用户交互。对于安卓开发者社区来说,G1手机是一款伟大的商用设备,它提供了触摸屏、轨迹球和键盘多种交互方式。因为用户可以使用三种不同的机制与应用程序交互,我们不得不非常努力地思考所有可能的可能出现的问题,其中一个问题产生的原因让我们创建了”触摸模式”这种交互模式。
<p>譬如,显示文本列表的ApiDemos。用户可既可以使用轨迹球浏览列表也可以滚动列表并使用手指点击来浏览列表。在这种情况下的问题是selection(选择)。如果我们选择了一个位于列表顶部的条目,然后把列表向底部拖动,被选择的列表会发生什么情况呢?它应该继续保留选中状态并滚动出屏幕吗?在这种情况下,将会发生什么呢?如果接下来我又使用轨迹球的来进行选择呢?或者更糟的是,如果我按下轨迹球选择当前选中的项,但是这一项已经被我划出屏幕了。所以经过仔细考虑,我们决定移除selection。
<p>在”触摸模式”下没有焦点和”selection”,任何在网格列表中被选中的条目都会变成未被选中的状态只要用户处于”触摸模式”下。同样,当处于触摸模式的时候所有可以获得焦点的控件都会变成不可聚焦的状态。下面的图片将会告诉我们当用户先用轨迹球选择一个条目然后再触摸它会发生什么状况。

《Android之TouchMode知多少》 利用滚动球或十字导航物理按键来选中item时的状态.png

《Android之TouchMode知多少》 图-2.png

这两张图看起来非常的抽象,如果不用手机演示一下很难理解它们表示什么意思。我们知道在早期版本的Android系统中,当我们点击ListView的某一个item的时候,这个item会有一个黄色背景色(现在是半透明的灰色),只不过这个背景色只存在于你的手指按住item的时候,当你的手指离开item的时候它就消失了。<p>当我们用方向物理按键或者轨迹球来选中ListView的某一个item的时候,这item也会出现黄色的背景,此时的背景不会消失,表示当前的item处于被选中状态如 图-1。这个时候,如果你再使用手指通过触摸屏幕选择某个的时候,你就会发现这个黄色的背景消失了,代替它的又是按下时的黄色状态,如 图-2。

为了使用户感觉这种方式比较自然,framework会在适当的时机重启selection/focus。例如,上个例子中,用户再次使用轨迹球的时候, “selection”(也就是那个黄色的选中状态)会重新出现在上次选中条目的地方。<p>这就是为么有些开发者会对在自定义View并且只能在移动轨迹球之后接收key events时感到困惑的原因。一旦应用处于触摸模式,他们就需要使用trackball(轨迹球)来退出触摸模式并且启用焦点。

Focusable in Touch Mode

现在你既然知道了再触摸模式下不存在焦点这么一说,但是不我不告诉你这并不完全正确。焦点可以以一种特殊的方式存在于触摸模式中,这种方式称之为”focusable in touch mode”。<p>这种模式为Edittext和ListView类似的组件而创建,这就是为么用户可以在不选中EditText的状态下就可以输入文字的原因。<p>当用于用手指触摸的屏幕的时候系统就会自动进入触摸模式。向触摸模式过渡期间会发生什么取决于用当前点击的组件可不可以在触摸模式下获得焦点。<p>如果用户点击的控件可以在触摸模式下获得焦点的,那么它就会获得焦点。否则,任何控件都不会获得焦点。例如图-3,当用户触摸屏幕的时候,EditText会获得焦点。

《Android之TouchMode知多少》 图-3.png

Focusable in touch mode是一种属性,你可以在代码中通过setFocusableInTouchMode(true)来设置它,也可以在xml通过android:focusableInTouchMode="true"设置它。

到这里,原文重要的部分我都翻译完了,我问题也算是迎刃而解了。最后,isFocusableInTouchMode()这个方法就是用来获得控件在触摸模式下是否需要焦点的,大家可以去实际操作一下看一下效果。and then ,继续搞起View源码。
—生活以痛吻我,我扔报之以歌。

    原文作者:OFU张硕
    原文地址: https://www.jianshu.com/p/ea931d09c3d6
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞