关于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

相关文章

MVC(Model-View-Controller)和MVVM(Model-View-ViewModel)

1、MVC MVC(Model-View-Controller) 是一种常用的架构模式,用于分离应用程序的逻辑、数据和展示。它通过三个核心组件(模型、视图和控制器)将应用程序的业务逻辑与用户界面隔离,促进代码的可维护性、可扩展性和模块化。在 MVC 模式中,各组件可以与多种设计模式结合使用,以增强灵活性和可维护性。以下是 MVC 各组件与常见设计模式的关系和作用: 1. Model(模型)

MFC中App,Doc,MainFrame,View各指针的互相获取

纸上得来终觉浅,为了熟悉获取方法,我建了个SDI。 首先说明这四个类的执行顺序是App->Doc->Main->View 另外添加CDialog类获得各个指针的方法。 多文档的获取有点小区别,有时间也总结一下。 //  App void CSDIApp::OnApp() {      //  App      //  Doc     CDocument *pD

Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.B

一个bug日志 FATAL EXCEPTION: main03-25 14:24:07.724: E/AndroidRuntime(4135): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.syyx.jingubang.ky/com.anguotech.android.activity.Init

自定义view中常用到哪些方法作用分别是什么

目录 构造函数onMeasure(int widthMeasureSpec, int heightMeasureSpec)onDraw(Canvas canvas)onLayout(boolean changed, int left, int top, int right, int bottom)onTouchEvent(MotionEvent event)onSizeChanged(int

myEclipse失去焦点时报错Unhandled event loop exception的解决方案

一句话:百度杀毒惹的祸。。。。果断卸载后问题解决。

android 动画 ——视图动画(View Animation)

android动画分为视图动画(View Animation)、属性动画(Property Animation) 想看属性动画(Property Animation):请移步至http://blog.csdn.net/u013424496/article/details/51700312 这里我们来说下视图动画(View Animation)的纯代码写法,还有一种是xml调用, 对于xml调

Android 自定义View控件,实现跟随手指触摸移动的小球

Android UI组件是通过继承View类,然后绘制内容,比如ImageView,TextView等组件都是继承View类。 当Android系统提供的组件功能不能满足需求时,可以通过继承View类重写一个或多个方法,派生自定义的组件,View类常用重写方法: 1.构造器:View子类最基本的重写方法 protected voidonDraw(Canvas canvas) public

mac捕获android任意应用的view视图

一、uiautomatorviewer 介绍    iautomatorviewer是android SDK自带的一个元素定位工具。通过截屏并分析XML布局文件的方式,为用户提供控件信息查看服务。 使用uiautomatorviewer,你可以检查一个应用的UI来查看应用的布局和组件以及相关的属性。该工具位于SDK目录下的tools\bin子目录下。 二、效果图 下图演示 截取微信的 v

spring boot 的tomcat部署,自己的view层不做映射

需要复写继承该类SpringBootServletInitializer 的config方法,网上有些直接写主入口类的,部署是不对的。一定要复写config方法。

IOS View编程指南笔记

我们所看到的程序 对于一切IOS APP来说,我们看的的内容,都是UIView所呈现的。 UIView如场景,UIWindow如舞台,UIView粉墨登场在UIWindow这个舞台上,使我们看到丰富多彩的界面UI。UIWindow本身没有任何内容,它只提供了一个场所来让这些UIView来显示,切换。 通常,一个APP仅有一个UIWindow作为显示的场所,当我们要进行多屏显示时,才会使用到多