android中调用requestFocus()的详细过程

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
        }
}

ViewRoot中的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);




你可能感兴趣的:(android)