问题描述:插入鼠标后,滑动鼠标,然后调出系统的关机菜单,菜单无法获取焦点,即使使关机菜单的view主动调用requestFocus方法,仍然无法获取到焦点。
分析:
frameworks/base/core/java/android/view/View.java
public boolean requestFocus(int direction, Rect previouslyFocusedRect) {//一般情况下view获取焦点调用方法
return requestFocusNoSearch(direction, previouslyFocusedRect);
}
private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
// need to be focusable
if (!canTakeFocus()) {//view当前处于可获取焦点状态
return false;
}
// need to be focusable in touch mode if in touch mode
if (isInTouchMode() &&
(FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {//当前处于touch mode,并且view没有设置foucusableInTouchMode=“true”属性
return false;
}
// need to not have any parents blocking us
if (hasAncestorThatBlocksDescendantFocus()) {
return false;
}
if (!isLayoutValid()) {
mPrivateFlags |= PFLAG_WANTS_FOCUS;
} else {
clearParentsWantFocus();
}
handleFocusGainInternal(direction, previouslyFocusedRect);
return true;
}
public final boolean requestFocusFromTouch() {
// Leave touch mode if we need to
if (isInTouchMode()) {//当前处于touch mode 仍然可以获取焦点
ViewRootImpl viewRoot = getViewRootImpl();
if (viewRoot != null) {
viewRoot.ensureTouchMode(false);
}
}
return requestFocus(View.FOCUS_DOWN);
}
可以看到,如果我们只通过调用requestFocus()方法去获取焦点,那么如果当前处于touch mode,并且view没有设置foucusableInTouchMode="true"属性则无法获取焦点。
View提供了requestFocusFromTouch()方法。调用此方法可以将焦点集中到特定view或其子view之一。 requestFocusFromTouch是requestFocus() 的一种特殊情况,它允许在touch模式下将无法获取到焦点的view在被触摸时获取到焦点。
解决:
所以我们其实可以通过两种方式来在touch mode下获取焦点:
1.代码中主动调用view.requestFocusFromTouch()方法
2.xml文件中为view配置foucusableInTouchMode="true"属性