[Android开发-TV] 焦点请求流程

焦点请求流程

当我们希望某个视图获取焦点时,会调用View.requestFocus()方法,那么requestFocus()干了什么,我们可以以它作为切入点来观察焦点的请求流程。

public final boolean requestFocus() {
       return requestFocus(View.FOCUS_DOWN);
}

按照遥控器上下左右键,无参方法默认以下作为焦点的请求方向
最终会调用到requestFocusNoSearch方法,传递方向和之前获得焦点的视图的区域

private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
        // 判断当前视图能否获得焦点
        if (!canTakeFocus()) {
            return false;
        }

        // 判断在触摸模式下是否可聚焦
        if (isInTouchMode() &&
            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
               return false;
        }

        // 判断父视图是否阻止了当前视图获得焦点
        if (hasAncestorThatBlocksDescendantFocus()) {
            return false;
        }
		// 判断当前视图是否可以进行layout,不可layout时,设置标记期望获得焦点
        if (!isLayoutValid()) {
            mPrivateFlags |= PFLAG_WANTS_FOCUS;
        } else {
        	// 此视图可以进行layout,清除父视图的期望获得焦点标记
            clearParentsWantFocus();
        }
		//
        handleFocusGainInternal(direction, previouslyFocusedRect);
        return true;
    }

非搜索的情况下请求焦点会检查当前视图是否可以获取焦点,最后赋予当前视图焦点
下面看handleFocusGainInternal方法

void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
        if (DBG) {
            System.out.println(this + " requestFocus()");
        }
		//检查当前视图是否已经获得焦点
        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
        	//设置已获得焦点的标记
            mPrivateFlags |= PFLAG_FOCUSED;
			//获取之前的焦点
            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;

            if (mParent != null) {
            	//通知父视图当前视图请求焦点了
                mParent.requestChildFocus(this, this);
                //更新此ViewGroup集群中获得焦点的视图
                updateFocusedInCluster(oldFocus, direction);
            }

            if (mAttachInfo != null) {
            	//通知全局焦点监听器焦点视图更新
                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
            }
			//调用onFocusChanged方法
            onFocusChanged(true, direction, previouslyFocusedRect);
            //刷新Drawable状态
            refreshDrawableState();
        }
    }

handleFocusGainInternal方法会在UI表现上更新视图的焦点状态,并且调用onFocusChanged方法,我们可以在onFocusChanged方法的监听器上放大缩小获得焦点的视图

结论:requestFocus()方法会判断当前视图能否获得焦点,然后在视图层次结构之间保持视图的稳定更新获得焦点的视图并且调用监听器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值