1 简介
setDescendantFocusability(int focusability)
是 ViewGroup
的方法,其作用是设置 ViewGroup
的子View获取焦点的能力。
科普一下英文单词
descendant
英[dɪˈsendənt] 美[dɪˈsɛndənt] 复数:[descendants]
n. 后裔; 后代; (由过去类似物发展来的) 派生物; 弟子;
adj.下降的; 祖传的; |
[例句]They are descendants of the original English and Scottish settlers.
他们是最初的英格兰和苏格兰定居者的后代。
2 实现
setDescendantFocusability(int focusability)
的具体实现代码如下所示:
/**
* Set the descendant focusability of this view group. This defines the relationship
* between this view group and its descendants when looking for a view to
* take focus in {@link #requestFocus(int, android.graphics.Rect)}.
*
* @param focusability one of {@link #FOCUS_BEFORE_DESCENDANTS}, {@link #FOCUS_AFTER_DESCENDANTS},
* {@link #FOCUS_BLOCK_DESCENDANTS}.
*/
public void setDescendantFocusability(int focusability) {
switch (focusability) {
case FOCUS_BEFORE_DESCENDANTS:
case FOCUS_AFTER_DESCENDANTS:
case FOCUS_BLOCK_DESCENDANTS:
break;
default:
throw new IllegalArgumentException("must be one of FOCUS_BEFORE_DESCENDANTS, "
+ "FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS");
}
mGroupFlags &= ~FLAG_MASK_FOCUSABILITY;
mGroupFlags |= (focusability & FLAG_MASK_FOCUSABILITY);
}
setDescendantFocusability(int focusability)
方法可以传入的参数只有三种,
分别为:FOCUS_BEFORE_DESCENDANTS
、FOCUS_AFTER_DESCENDANTS
和 FOCUS_BLOCK_DESCENDANTS
,从源码中也能看出来,除了这三种参数,传入其它参数会抛出非法参数异常。
FOCUS_BEFORE_DESCENDANTS
该参数表明 ViewGroup
自身先处理焦点,如果没有处理则分发给子View进行处理。
FOCUS_AFTER_DESCENDANTS
该参数表明子View优先处理焦点,如果所有的子View都没有处理,则 ViewGroup
自身再处理。
FOCUS_BLOCK_DESCENDANTS
该参数表明 ViewGroup
自身处理焦点,不会分发给子View处理。
而这三种参数实际上是在 requestFocus(int direction, Rect previouslyFocusedRect)
方法中起作用的,如下源码所示。
/**
* {@inheritDoc}
*
* Looks for a view to give focus to respecting the setting specified by
* {@link #getDescendantFocusability()}.
*
* Uses {@link #onRequestFocusInDescendants(int, android.graphics.Rect)} to
* find focus within the children of this group when appropriate.
*
* @see #FOCUS_BEFORE_DESCENDANTS
* @see #FOCUS_AFTER_DESCENDANTS
* @see #FOCUS_BLOCK_DESCENDANTS
* @see #onRequestFocusInDescendants(int, android.graphics.Rect)
*/
@Override
public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
if (DBG) {
System.out.println(this + " ViewGroup.requestFocus direction="
+ direction);
}
int descendantFocusability = getDescendantFocusability();
switch (descendantFocusability) {
case FOCUS_BLOCK_DESCENDANTS:
return super.requestFocus(direction, previouslyFocusedRect);
case FOCUS_BEFORE_DESCENDANTS: {
final boolean took = super.requestFocus(direction, previouslyFocusedRect);
return took ? took : onRequestFocusInDescendants(direction, previouslyFocusedRect);
}
case FOCUS_AFTER_DESCENDANTS: {
final boolean took = onRequestFocusInDescendants(direction, previouslyFocusedRect);
return took ? took : super.requestFocus(direction, previouslyFocusedRect);
}
default:
throw new IllegalStateException("descendant focusability must be "
+ "one of FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS "
+ "but is " + descendantFocusability);
}
}
如果想让 RecyclerView
的子View优先获取焦点的话,就可以在布局中添加下面这一行代码。
android:descendantFocusability="afterDescendants"
或者在Java代码中添加下面这一行代码。
mRecyclerView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);