view中 public boolean requestFocus(int direction, Rect previouslyFocusedRect) { return requestFocusNoSearch(direction, previouslyFocusedRect); } private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) { // need to be focusable if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE || (mViewFlags & VISIBILITY_MASK) != VISIBLE) { return false; } // need to be focusable in touch mode if in touch mode if (isInTouchMode() && (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) { return false; } // need to not have any parents blocking us if (hasAncestorThatBlocksDescendantFocus()) {//判断父视图是否阻止子视图获得焦点 return false; } handleFocusGainInternal(direction, previouslyFocusedRect);//进行具体的焦点获取 return true; } void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) { if (DBG) { System.out.println(this + " requestFocus()"); } if ((mPrivateFlags & FOCUSED) == 0) { mPrivateFlags |= FOCUSED; if (mParent != null) { mParent.requestChildFocus(this, this);//第一个参数是child视图,第二个是focused视图,该函数内部进行递归调用 } //注意时态,xxxed()和xxx()的区别是,前者是执行完之后回调,后者是在执行前回调 onFocusChanged(true, direction, previouslyFocusedRect); refreshDrawableState(); if (AccessibilityManager.getInstance(mContext).isEnabled()) { notifyAccessibilityStateChanged(); } } } 一般来说,父视图是ViewGroup,requestChildFocus在ViewGroup中的实现 public void requestChildFocus(View child, View focused) { if (DBG) { System.out.println(this + " requestChildFocus()"); } if (getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS) { return; } // Unfocus us, if necessary super.unFocus(); // We had a previous notion of who had focus. Clear it. if (mFocused != child) { if (mFocused != null) { mFocused.unFocus(); } mFocused = child; } if (mParent != null) { mParent.requestChildFocus(this, focused);//最终会递归到ViewRoot中的equestChildFocus } } ViewRootImpl中的requestChildFocus public void requestChildFocus(View child, View focused) { checkThread();//确保在UI线程中 if (mFocusedView != focused) {//其实ViewGroup中已经检查过,mFocusedView一定不是目标焦点视图 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mFocusedView, focused); scheduleTraversals();//发起View遍历请求 } mFocusedView = mRealFocusedView = focused; if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Request child focus: focus now " + mFocusedView); view中 public boolean requestFocus(int direction, Rect previouslyFocusedRect) { return requestFocusNoSearch(direction, previouslyFocusedRect); } private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) { // need to be focusable if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE || (mViewFlags & VISIBILITY_MASK) != VISIBLE) { return false; } // need to be focusable in touch mode if in touch mode if (isInTouchMode() && (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) { return false; } // need to not have any parents blocking us if (hasAncestorThatBlocksDescendantFocus()) {//判断父视图是否阻止子视图获得焦点 return false; } handleFocusGainInternal(direction, previouslyFocusedRect);//进行具体的焦点获取 return true; } void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) { if (DBG) { System.out.println(this + " requestFocus()"); } if ((mPrivateFlags & FOCUSED) == 0) { mPrivateFlags |= FOCUSED; if (mParent != null) { mParent.requestChildFocus(this, this);//第一个参数是child视图,第二个是focused视图,该函数内部进行递归调用 } //注意时态,xxxed()和xxx()的区别是,前者是执行完之后回调,后者是在执行前回调 onFocusChanged(true, direction, previouslyFocusedRect); refreshDrawableState(); if (AccessibilityManager.getInstance(mContext).isEnabled()) { notifyAccessibilityStateChanged(); } } } 一般来说,父视图是ViewGroup,requestChildFocus在ViewGroup中的实现 public void requestChildFocus(View child, View focused) { if (DBG) { System.out.println(this + " requestChildFocus()"); } if (getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS) { return; } // Unfocus us, if necessary super.unFocus(); // We had a previous notion of who had focus. Clear it. if (mFocused != child) { if (mFocused != null) { mFocused.unFocus(); } mFocused = child; } if (mParent != null) { mParent.requestChildFocus(this, focused);//最终会递归到ViewRoot中的equestChildFocus } } ViewRootImpl中的requestChildFocus public void requestChildFocus(View child, View focused) { checkThread();//确保在UI线程中 if (mFocusedView != focused) {//其实ViewGroup中已经检查过,mFocusedView一定不是目标焦点视图 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mFocusedView, focused); scheduleTraversals();//发起View遍历请求 } mFocusedView = mRealFocusedView = focused; if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Request child focus: focus now " + mFocusedView);