关于ViewTreeObserver的理解

Bun轻量级依赖注入框架dunx实战:无reflect-metadata的NestJS风格DI方案 依赖注入(DI)作为一种实现控制反转(IoC)的核心设计模式,通过将对象的创建与依赖管理委托给外部容器,显著提升了代码的解耦性、可测试性和可维护性。其原理在于容器根据预先定义的依赖关系图,在运行时自动解析并注入所需实例,从而将业务逻辑与对象创建逻辑分离。这一技术价值在构建大型复杂应用时尤为突出,能够有效管理模块间的依赖关系,降低代码耦合度。在Node.js生态中,NestJS框架基于装饰器和reflect-metadata的DI方案已成为企业级开发的事实标准,但其运行时开销和配置复杂度在追求极致性能的场景下 阅读详情
作用:通过名字就可以知道它是View树的观察者,当View树的发生变化的时候会发出通知。ViewTreeObserver是不能被应用程序实例化的,因为它是由视图提供的,通过view.getViewTreeObserver()获取。


熟悉观察者模式的人应该很容易想到,为了能够相应的通知,我们肯定需要注册监听。下面来看看我们可以注册哪些监听。


1、当在一个视图树中的焦点状态或者可见性发生改变时调用OnGlobalFocusChangeListener的onGlobalFocusChanged()函数。


public void addOnGlobalFocusChangeListener (ViewTreeObserver.OnGlobalFocusChangeListener listener)
1
1
2、当在一个视图树中的焦点状态或者可见性发生改变时调用OnGlobalFocusChangeListener的onGlobalFocusChanged()函数。


public void addOnGlobalLayoutListener (ViewTreeObserver.OnGlobalLayoutListener listener)
1
1
3、当一个视图树将要绘制时调用OnPreDrawListener的onPreDraw()函数


public void addOnPreDrawListener (ViewTreeObserver.OnPreDrawListener listener)
1
1
4、当一个视图发生滚动时调用OnScrollChangedListener的onScrollChanged()函数


public void addOnScrollChangedListener (ViewTreeObserver.OnScrollChangedListener listener)  
1
1
5、当一个触摸模式发生改变时调用OnTouchModeChangeListener的onTouchModeChanged()函数


public void addOnTouchModeChangeListener (ViewTreeObserver.OnTouchModeChangeListener listener)
1
1
6、当一个视图树绘制时调用OnDrawListener的onDraw()函数


addOnDrawListener(ViewTreeObserver.OnDrawListener listener) 
1
1
7、当View树绑定到window上的时候回调OnWindowAttachListener的onWindowAttached() 函数,当它从window上解绑时调用OnWindowAttachListener的onWindowDetached()


addOnWindowAttachListener(ViewTreeObserver.OnWindowAttachListener listener) 
1
1
8、当window的焦点状态发生改变时,调用OnWindowFocusChangeListener的onWindowFocusChanged函数


addOnWindowFocusChangeListener(ViewTreeObserver.OnWindowFocusChangeListener listener) 
1
1
对应这些注册的监听,还有相应的删除监听


public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)


public void removeOnGlobalFocusChangeListener (ViewTreeObserver.OnGlobalFocusChangeListener victim)


public void removeOnPreDrawListener (ViewTreeObserver.OnPreDrawListener victim)


public void removeOnScrollChangedListener (ViewTreeObserver.OnScrollChangedListener victim)


public void removeOnTouchModeChangeListener (ViewTreeObserver.OnTouchModeChangeListener victim)


public void removeOnDrawListener(ViewTreeObserver.OnDrawListener victim) 


public void removeOnWindowAttachListener(ViewTreeObserver.OnWindowAttachListener victim) 


public void removeOnWindowFocusChangeListener(ViewTreeObserver.OnWindowFocusChangeListener victim) 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
上面注册的监听都是View树发生变化的时候,会被自动触发回调,如果我们希望手动触发回调,可以调用下面函数


public final void dispatchOnGlobalLayout ()


手动触发OnGlobalLayoutListener的onGlobalLayout()函数回调


public final boolean dispatchOnPreDraw ()


手动触发OnPreDrawListener的onPreDraw()函数的回调
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
另外还是一个指示当前的ViewTreeObserver是否可用的函数。


public boolean isAlive ()


当observer不可用时,任何方法的调用(除了这个方法)都将抛出一个异常。
1
2
3
1
2
3
应用场景1:获取View的宽高


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final MyImageView myImageView = (MyImageView) findViewById(R.id.imageview);
    int height = 0;
    int width =  0 ;
    ViewTreeObserver vto = myImageView.getViewTreeObserver();
    vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        public boolean onPreDraw() {
            int height = myImageView.getMeasuredHeight();
            int width = myImageView.getMeasuredWidth();
            return true;
        }
    });
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
因为回调OnPreDrawListener的onPreDraw,表示这个View准备进行绘制,在绘制之前,这个View的宽高肯定是已经测量好了,所以这个时机是可以得到view的宽高的。


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final MyImageView myImageView = (MyImageView) findViewById(R.id.imageview);
    int height = 0;
    int width =  0 ;


    ViewTreeObserver vto = myImageView.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            myImageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            int height = myImageView.getHeight();
            int width = myImageView.getWidth();
        }
    }); 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
当view的可见状态发生变化的时候回调OnGlobalLayoutListener的onGlobalLayout()函数,这个时候View的宽高肯定也是已经测量好了,所以这个时机是可以得到view的宽高的。


应用场景2:Activity跳转动画


ViewTreeObserver还可以用来监听根布局,用来实现Activity跳转动画,核心代码如下:


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
    rootView = findViewById(R.id.root);
    if (savedInstanceState == null) {
        rootView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                rootView.getViewTreeObserver().removeOnPreDrawListener(this);
                startRootAnimation();
                return true;
            }
        });
    }
}

因为在绘制之前会触发OnPreDrawListener的onPreDraw()函数,这个时候可以执行跳转动画。


应用场景3:测量软键盘状态和高度


ViewTreeObserver.OnGlobalLayoutListener mListener = new ViewTreeObserver
            .OnGlobalLayoutListener() {
        public void onGlobalLayout() {
            Rect r1 = new Rect();
            root.getWindowVisibleDisplayFrame(r1);
            Log.e("TAG",r1.bottom+"") ; 
        }
    };
root.getViewTreeObserver().addOnGlobalLayoutListener(mListener);


在根布局加入GlobalLayoutListener监听,通过getWindowVisibleDisplayFrame方法可以观察可见区域的变化,键盘打开后 会影响可见区域的大小,导致Rect的底部r1.bottom变小。
Android ViewTreeObserver使用详解与示例 本文还有配套的精品资源,点击获取 简介:在Android开发中, ViewTreeObserver 提供了一个监测视图树变化的机制,包括视图加载、绘制、尺寸变化等。本Demo展示了如何利用 ViewTreeObserver 来计算组件的大小,并详细讲解了其工作原理、使用方法和注意事项。开发者可以借此实现对应用界面尺寸的精确控制和优化,如自适应布局... 阅读详情

相关推荐

告别配置烦恼!保姆级教程:在Windows 10/11上为QT5.14.2配置MSVC2017编译器(附VS2022组件避坑指南)

本文提供了一份详细的保姆级教程,指导如何在Windows 10/11上为QT5.14.2配置MSVC2017编译器,包括VS2022组件避坑指南。从环境准备到关键配置,再到调试工具验证和Qt Creator中的编译器设置,一步步解决常见问题,帮助开发者快速搭建稳定可靠的开发环境。

weixin_30615767的博客 502

【Android】ViewTreeObserver的使用

ViewTreeObserver的使用

每天不是在写bug就是在写bug的路上 3537

新手必看:如何用Python模拟电动助力转向系统(EPS)的传感器信号处理

本文详细介绍了如何使用Python模拟电动助力转向系统(EPS)的传感器信号处理流程,包括转向力矩、转向角度和车速信号的生成与滤波处理。通过实战代码示例,帮助开发者理解ECU如何计算助力扭矩,并提供了可视化分析和性能优化建议,适合汽车电子系统开发新手学习。

weixin_28327051的博客 354

android ViewTreeObserver详细讲解

声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnblogs.com/ Android中文翻译组:http://goo.gl/6vJQl 正文 一、结构 public final class ViewTreeObserver extends Object java.lang.Object android.view

WeLoveSunFlower的专栏 1331

XGBoost与Embedding混合建模实战解析

在机器学习领域,特征工程与模型融合是提升预测性能的关键技术。Embedding技术通过将高维稀疏特征(如文本、ID类数据)转化为低维稠密向量,有效捕获语义关联;而XGBoost作为强大的集成学习算法,擅长处理结构化特征并进行自动特征组合。两者结合的混合架构(如Semantic Boosted Trees)在金融风控和推荐系统等场景中展现出显著优势,尤其在处理用户行为序列、商品ID等复杂特征时,相比传统方法能获得更好的模型效果。本文通过电商推荐和金融反欺诈等案例,详解如何实现Embedding+XGBoost

weixin_28718641的博客 325

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决

pgsql数据库通过备份数据库文件进行还原时,如果表中有自增序列,还原后可能会出现重复的序列,此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。还原数据库时把序列取消勾选,选择不还原序列。因为还原表的同时,会自动将自增序列还原上去,此处勾选会导致数据库重复创建序列。点击还原数据库完毕后,可以看到序列仅有一个,没有出现重复序列。但此时的序列当前值是从1开始的,需要重置。点击菜单“其它”-》“序列”,可以看到有多个重复序列。

奋斗鱼 1043

getViewTreeObserver的用法

为什么80%的码农都做不了架构师?>>> ...

weixin_34161029的博客 1901

智慧楼宇解决方案-全套大合集

智慧楼宇解决方案,楼宇能耗-环境-设备统一管控解决方案。

byte58的博客 2592

ViewTreeObserver理解

ViewTreeObserver类是一个监听View中各种状态(焦点的改变、布局的改变、触摸模式的改变、绘制视图前、滚动状态等)。 获得ViewTreeObserver类实例的方式: ViewTreeObserver vto = 视图.getViewTreeObserver();   //相应的是处理该视图的事件。 分别实现上述状态改变的方法: 布局的改变: 设置visible和in

peiyuWang_2015的博客 670

阿里平头哥与华为芯片的比较

阿里平头哥与华为芯片代表了中国AI芯片领域的两种典型发展路径:平头哥通过兼容CUDA生态快速切入市场,以较低成本提供接近国际水平的AI算力;华为则坚持全栈自研路线,构建从芯片到框架的完整技术体系,更注重供应链安全和自主可控。从短期来看,平头哥PPU在单卡性能参数上全面超越昇腾910B,接近英伟达H20水平,且成本优势明显,有望在云服务和互联网应用领域取得更大市场份额。而华为昇腾则凭借全栈自研和端边云协同优势,在政企市场和科研领域更具竞争力。

shao.bing的专栏 3998

39、信号流图:解决线性代数方程组的图论方法

本文介绍了信号流图理论在求解线性代数方程组中的应用,重点阐述了Coates方法和Mason方法的原理、步骤及对比分析。通过图论视角,将矩阵运算转化为对有向图结构的分析,利用1-因子、1-阶连接、前向路径和反馈回路等概念,推导出方程组解的拓扑公式。文章结合具体实例演示两种方法的计算过程,并总结其在电路分析、控制系统和通信系统等领域的拓展应用,展示了信号流图理论的直观性与有效性。

pear55的博客 88

ViewTreeObserver以及对view组件布局和绘制过程drawable的理解

我们知道在oncreate中View.getWidth和View.getHeight无法获得一个view的高度和宽度,这是因为View组件布局要在onResume回调后完成。所以现在需要使用getViewTreeObserver().addOnGlobalLayoutListener()来获得宽度或者高度。这是获得一个view的宽度和高度的方法之一。OnGlobalLayoutListener 是

qq_28192929的博客 328

使用C#实现的多人语音视频系统:WebSocket与WebRTC集成

通过上述的代码示例,我们可以使用C#编写一个多人语音视频系统,该系统集成了WebSocket和WebRTC技术。当然,这只是一个简单的示例,实际的多人语音视频系统可能需要更多的功能和优化。通过结合这两种技术,我们可以实现实时的语音和视频通信,支持多人同时参与。在上述代码中,我们创建了一个WebSocket服务器,监听在本地的8080端口,并创建了一个WebRTC连接。接下来,我们将详细介绍如何使用C#编写一个多人语音视频系统,包括使用WebSocket建立连接和使用WebRTC进行实时通信。

TjsReact的博客 1634

ViewTreeObserver源码学习

ViewTreeObserver源码学习一、理解ViewTreeObserver概念ViewTreeObserver用来注册监听器,在视图树全局发生变化时收到通知。它不能被应用实例化,因为它是由视图提供,通过android.view.View#getViewTreeObserver()来获取。ViewTree:视图树。在Android中,所有视图由View和View的子类组成。ViewGroup也是

荷小筱的程式之旅 1057

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

ViewTreeObserver 监听View的状态

官方文档 https://developer.android.com/reference/android/view/ViewTreeObserverv 概述 近期碰到要再OnCreate中获取View绘制结束之后的宽高,用到了ViewTreeObserver.OnGlobalLayoutListener。 鉴于ViewTreeObserver的确比较实用,于是写本文记录下。 官方描述 A v...

许佳佳的博客 2232

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

android ViewTreeObserver

android ViewTreeObserver从字面意思可以看出是View树的观察者。用法大致就是添加各种回调函数,包括但不限于draw方法开始执行,触摸模型改变,窗口状态改变,layout状态改变。 /**view树是否绑定到了Window上 */ public interface OnWindowAttachListener { ...

weixin_30739595的博客 104

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

android observer 实例,Java android.view.ViewTreeObserver 代码实例

以下是展示如何使用android.view.ViewTreeObserver的最佳示例。 我们使用了代码质量辨别算法从开源项目中提取出了最佳的优秀示例。实例 1/*** Clean-up the resources attached to this object. This needs to be called* when the ImageView is no longer used. A go...

weixin_30129025的博客 272

视图树的观察者 ViewTreeObserver

http://www.cnblogs.com/xingfuzzhd/archive/2013/06/25/3154674.html   Android ViewTreeObserver简介   一、结构 public final class ViewTreeObserver extends Object java.lang.Object androi

aiqing0119的专栏 1821

android ViewTreeObserver地址

Android ViewTreeObserver地址:::: http://www.cnblogs.com/xingfuzzhd/archive/2013/06/25/3154674.html

宇宙精英 798

view变化监听器ViewTreeObserver的简单使用(附小demo)

祝大家新年快乐,新的一年技术涨涨涨~~ ViewTreeObserver 有五个监听接口: interface ViewTreeObserver.OnGlobalFocusChangeListener   //当在一个视图树中的焦点状态发生改变时,所要调用的回调函数的接口类    interface ViewTreeObserver.OnGlobalLay

李洋洋的博客 1823

【Android】【ViewGroup】多个监听和回调的顺序

ViewTreeObserverLinearLayout ViewTreeObserverLinearLayout ViewTreeObserverView ViewTreeObserverView ViewTreeObserverView onFinishInflate ViewTreeObserverLinearLayout onFinishInflate ViewTre

zhangXiaoFan_的博客 1354

Android 学习 之 API文档汇总(不断更新)

这是我自己的总结,我觉得自己现在有必要把看过的,理解了的API内容放在这里记录一下,以便不时之需,希望也能给你带来一定的帮助吧。   开始之前,查阅一下农民伯伯的文章吧,Android 中文 API(123) —— AbsListView    1.ViewTreeObserver.java : 从类名的字面意思上看,这个应该是一个观察者,用来观察树形视图的变化的,其中的:     1....

172

android视图学习---从源码角度来理解onMeasure过程

前面的几篇文章写的都非常好的,非常的了不起,介绍的非常的详细 view的绘制:onMeasure onLayout onDraw 执行流程  【这里其实就是RootViewImpl 里面setView之后的一个流程】 这里是ViewRoot的子类,也叫实现类里面的ViewRootImpl android怎么把view添加到窗口的:这里面进一步让我们知道整个视图的组成是有window,phon

wust小吴 1497

Android中的ViewTreeObserver分析(一)

PS:本文系转载文章,阅读原文可读性会更好些,原文链接:https://mp.weixin.qq.com/s/zXHJsr4XSfPTynMpzN_mLw ps:源码是基于 android api 27 来分析的 在 Android 中,想要获取 View 的一些状态,比如说 View 的宽高发生了改变,可以使用 ViewTreeObserver 内部接口 OnGlobalLayoutListener 进行注册监听,见名知意,一看名字就知道它是 ViewTree 的观察者,一个界面包含多个 View 形成

qq_37837621的博客 1134

解析 ViewTreeObserver 源码(上)

主要内容:ViewTreeObserver 是被用来注册监听视图树的观察者,在视图树发生全局改变时将收到通知。本文从 ViewTreeObserver 源码出发,带你剖析 ViewTreeObserver 的设计及使用,并间接体会观察者模式、Android消息传递机制在其中的使用。这两天看代码看到了 ViewTreeObserver ,之前有接触过,但一直不太其到底在表达什么。这次既然又碰到了,那...

weixin_30587025的博客 165

监听View绘制完成

MView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // TODO Something } }); 为想要监听的View添加全局layout监听,在view.

qq_30234677的博客 1752
上一篇: 关于音频焦点的理解
下一篇: Android RemoteController使用
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值