关于View的焦点

2024-05-30 08:58
文章标签 view 焦点

本文主要是介绍关于View的焦点,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

##1.什么是View/ViewGroup的焦点,焦点的作用是什么?
从广义上来说,焦点就是用户当前正在或者下一步可能操作的目标,在按键模式下(现在大部分手机都是触摸模式)一般具有焦点的View都会高亮展示,以提示用户当前可以操作的目标。
从狭义上来说,焦点就是View中的mPrivateFlags成员字段被添加上了PFLAG_FOCUSED标示。

##2.View和ViewGroup中hasFocus方法的区别?

    //View的hasFocus方法public boolean hasFocus() {return (mPrivateFlags & PFLAG_FOCUSED) != 0;}//ViewGroup的hasFocus方法public boolean hasFocus() {return (mPrivateFlags & PFLAG_FOCUSED) != 0 || mFocused != null;}

上述是View的hasFocus方法就是去检查当前view的mPrivateFlags字段中是否具有PFLAG_FOCUSED,而ViewGroup的hasFocus方法出了检查PFLAG_FOCUSED,还可以检查mFocused变量,也就是说ViewGroup的hasFocus方法返回两种情况

  1. 当前ViewGroup自身就是焦点所有者
  2. 当前ViewGroup自身没有焦点,但是具有焦点的控件在其子View中,这个时候mFocused就是焦点链路上的一个节点
    焦点链路
    上述的绿色背景的节点就构成了一个焦点链路,最顶层的ViewGroup的mFocused执行第二层的ViewGroup,第二层的中的mFocused指向View,该View就是真正获取到焦点的控件

##3.View.requestFocus方法是怎么获取和释放焦点的?

    public final boolean requestFocus() {return requestFocus(View.FOCUS_DOWN);}public boolean requestFocus(int direction, Rect previouslyFocusedRect) {return requestFocusNoSearch(direction, previouslyFocusedRect);}private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {// need to be focusable// 检查当前View是否能具有焦点if ((mViewFlags & FOCUSABLE) != 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// 检查其所属的ViewGroup是否管控了焦点分发策略,后面会说道if (hasAncestorThatBlocksDescendantFocus()) {return false;}//开始焦点更换流程handleFocusGainInternal(direction, previouslyFocusedRect);return true;}

view的requestFocus方法先检查当前View是否具有获取焦点的资格,之后再检查是否在触摸模式下,如果在该模式下,则还会检查是否具有触摸模式的焦点资格(在控件系统中,存在两种模式,分别是按键模式和触摸模式)。之后会检查其ViewGroup是否允许子View获取焦点,当ViewGroup中具有FOCUS_BLOCK_DESCENDANTS标示时,就会阻止子View获取焦点,如果允许子View获取焦点,则开始焦点请求

      //如果当前View不是焦点控件,才进行后续操作if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {//给当前View加上焦点标示mPrivateFlags |= PFLAG_FOCUSED;//先找到最顶层的ViewGroup,之后根据焦点链路找到前一个真正的焦点控件View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;if (mParent != null) {// 通过mParent向上一级View回溯,通知ViewGroup焦点控件更换了,让ViewGroup更新焦点链路mParent.requestChildFocus(this, this);updateFocusedInCluster(oldFocus, direction);}if (mAttachInfo != null) {mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);}//通知焦点观察者,焦点改变了onFocusChanged(true, direction, previouslyFocusedRect);// 刷新视图展示,比如在按键模式下,具有焦点的控件会高亮显示refreshDrawableState();}

接下来看下ViewGroup的requestChildFocus方法:

    @Overridepublic void requestChildFocus(View child, View focused) {// 再次检查当前ViewGroup焦点拦截策略if (getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS) {return;}// Unfocus us, if necessarysuper.unFocus(focused);// 如果当前ViewGroup是之前的焦点链路上的一个节点,则mFocused节点去释放焦点(清空焦点标示)if (mFocused != child) {if (mFocused != null) {mFocused.unFocus(focused);}mFocused = child;}if (mParent != null) {//不断向上一集View回溯,直到更新了整个View树的焦点链路,注意这里的第一个参数不是之前的焦点控件了,而是当前ViewGroup了mParent.requestChildFocus(this, focused);}}

看下View的unFocus方法:

   void unFocus(View focused) {clearFocusInternal(focused, false, false);}void clearFocusInternal(View focused, boolean propagate, boolean refocus) {if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {//清空焦点标示mPrivateFlags &= ~PFLAG_FOCUSED;if (propagate && mParent != null) {//向上级View回溯,清空焦点mParent.clearChildFocus(this);}onFocusChanged(false, 0, null);refreshDrawableState();if (propagate && (!refocus || !rootViewRequestFocus())) {notifyGlobalFocusCleared(this);}}}

这篇关于关于View的焦点的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1016033

相关文章

ScrollView 往上滑动,里面的一个View停在某个位置的思路

1.scrollView的contentoffset 为view的左上角,减去此时scrollView的左上角 2.而且还不需要让那个红色的view removeFromSuperView ,直接self.view AddSubView 就会自动从原来的那个View脱离开来 3.以后遇到问题的思路。当发现UIView很许多奇特的效果的时候,思考它是不是在不断的改变父控件。 #pragma m

导航条下 ScrollView 第一个View去掉向下偏移的64px

self.automaticallyAdjustsScrollViewInsets=NO;      self.scrollView.contentInset=UIEdgeInsetsMake(-64, 0, 0, 0); self.automaticallyAdjustsScrollViewInsets=NO; 相同的意思。

android自定义View的和FramgentActivity的一个小坑

对于自定义View //加载样式TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TitleBarView, defStyleAttr, 0);setTitle(typedArray.getString(R.styleable.TitleBarView_main_title));//不能写成

Android自定义View学习笔记03

Android自定义View学习笔记03 参考gitHub上面的开源项目CircleImageView 预备知识 BitMap类 BitMap位图类,其中有一个嵌套类叫Bitmap.Config,内部有四个枚举值。这个类的作用是定义位图存储质量,即存储一个像素的位数,以及是否能显示透明、半透明颜色(Possible bitmap configurations. A bitmap co

Android自定义view学习笔记02

Android自定义view学习笔记02 本文代码来自于张鸿洋老师的博客之Android 自定义View (二) 进阶 学习笔记,对代码进行些许修改,并补充一些在coding过程中遇到的问题、学习的新东西。 相关代码 //CustomImageView.javapackage mmrx.com.myuserdefinedview.textview;import android.con

Android自定义view学习笔记01

Android自定义view学习笔记01 昨天看博客的时候看到鸿洋老师的博客里面有关于自定义view的学习教程。一直深感所掌握的东西太少太杂,按照他的Android 自定义View (一)所讲内容,代码实践。根据实际情况稍作修改,并且补充一些在代码过程中知识点,做此笔记。 相关代码 //CustomView01.javapackage mmrx.com.myuserdefinedvi

【Android面试八股文】在 Android 的 View 分发机制中有哪些反向制约的方法?

文章目录 一、在 Android 的 View 分发机制中有哪些反向制约的方法?1.1 `requestDisallowInterceptTouchEvent` 方法1.1.1 源码分析 1.2 事件回调方法中干预父 View 的行为1.2.1 示例代码 1.3 总结 一、在 Android 的 View 分发机制中有哪些反向制约的方法? 在 Android 的 View 分

rails中each do在view层中显示问题

有的时候会将一些数据  逐条列在view层上 但是 今天出了个问题  就是循环结束后会将  数组本身也显示在view中 原来是应该将  =@[param].each   改为 -@[param].each

【Android面试八股文】来说一说Activity,Window,View三者的联系和区别吧

文章目录 ActivityWindowView为什么需要 Window?Window和View的关系Activity与Window的关系示例流程图示总结扩展阅读 在Android应用程序开发中, Activity、Window 和 View 是构建用户界面的核心组件。它们之间有着紧密的联系,但角色和职责各不相同。下面是对它们联系和区别的详细解释: Ac

【Android面试八股文】自定义View执行invalidate()方法为什么有时候不会回调onDraw()?

文章目录 一、自定义View执行invalidate()方法为什么有时候不会回调onDraw()?1.1 invalidate 软件绘制流程1.2 invalidate源码分析1.2.1 skipInvalidate()方法1.2.2 invalidateChild方法1.2.2.1 硬件加速绘制1.2.2.2 软件刷新 1.2.3 小结 一、自定义View执行invalida