首先要明确一点的是,view要获取焦点,就必须具备获取焦点的能力(focusable)。Android在API中提供了两个方法来更改view是否能够获得焦点

void setFocusable(boolean focusable)
void setFocusableInTouchMode(boolean focusableInTouchMode)

这两个方法通过传入的参数是true或者false来控制view是否具有获得焦点的能力,在xml文件中对应同样的属性定义。要说明的一点是,方法1如果设置为了false,则isFocusable()和isFocusableInTouchMode()均为false。

例如,对于一个EditText类型的view调用该方法,并传入参数false,此时,再点击屏幕上的edit text,则无法获取焦点。

因此,在touch mode下,view要获得焦点,首先要设置其是focusable的。当然,特定view默认就是focusable的,比如edit text。

具备焦点能力后,Android提供了两个方法来获得焦点:

  • requestFocus()
  • requestFocusFromTouch()
从方法名就能看出两个方法的区别。其差异在各种博客中都提到的是:requestFocus在几种特殊情况下不能够获得焦点

  1. 调用requestFocus获取焦点的view不支持Focus。比如,button。
  2. 调用requestFocus获取焦点的view支持Focus,但不支持touch mode下的Focus。
这个比较好理解,就不举例来说明了。值得一提的是,requestFocuFromTouch调用后,该view会从touch mode变成非touch mode。其实,从源码就能看出
public final boolean requestFocusFromTouch() {
     // Leave touch mode if we need to
     if (isInTouchMode()) {
         ViewRootImpl viewRoot = getViewRootImpl();
         if (viewRoot != null) {
             viewRoot.ensureTouchMode(false);
         }
     }
     return requestFocus(View.FOCUS_DOWN);
}
如果需要的话,view会离开touch mode。