本篇依然讲的是焦点方面的问题,还是老样子,先看下出问题的现象,gif走起~
从动图上可以看到,进入二级页面,焦点向下移动,编辑框没有获取到焦点,后向上移动焦点,才获取到,是不是很神奇?
我们知道EditText和Button一样,是默认可获取焦点的,但是这里面没有获取到,这里面页面不是listview,第一个item是封装了EditText的控件,下面的其他item是单独另一种风格封装的控件。
思路:
1、EditText被父View焦点拦截了?
2、焦点搜索规则导致向下移动,EditText不是最佳的可以获取焦点的view?
首先,迅速排除掉了第一个可能性,因为代码中没有设置拦截子view focus焦点。
那么重点看下第二个思路,依然从源码处入手,焦点搜索查找由
frameworks/base/core/java/android/view/FocusFinder.java负责。
//查找焦点,root是根view,指的是DecorView,focused指的是当前已经获取到焦点的view,direction是焦点移动方向
public final View findNextFocus(ViewGroup root, View focused, int direction) {
return findNextFocus(root, focused, null, direction);
}
1、查找
private View findNextFocus(ViewGroup root, View focused, Rect focusedRect, int direction) {
View next = null;
//我这里,focused为null
if (focused != null) {
next = findNextUserSpecifiedFocus(root, focused, direction);
}
if (next != null) {
return next;
}
//初始化承载可以获取焦点的view的list
ArrayList<View> focusables = mTempList;
try {
//查找前先清除list
focusables.clear();
//调用根view的获取可以focusable的view并且添加到list中去
root.addFocusables(focusables, direction);
if (!focusables.isEmpty()) {
//获取到焦点view的list,继续查找
next = findNextFocus(root, focused, focusedRect, direction, focusables);
}
} finally {
focusables.clear();
}
return next;
}
2、遍历查找根view下的所有可以获取焦点的view,并且放到list集合去。
ViewGroup.java addFocusables方法
@Override
public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
final int focusableCount = views.size();
//获取当前viewGroup焦点能力
final int descendantFocusability = getDescendantFocusability();
//如果不是阻塞子view获取焦点,那么开始遍历子view
if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
if (shouldBlockFocusForTouchscreen()) {
focusableMode |= FOCUSABLES_TOUCH_MODE;
}
final int count = mChildrenCount;
final View[] children = mChildren;
//开始遍历
for (int i = 0; i < count; i++) {
final View child = children[i];
//如果子view可见。
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
child.addFocusables(v