Android开发艺术探索笔记(11),kotlin枚举

这里写图片描述

代码中看出我们只需给View设置默认的宽/高(mWidht/mHeight)就行。

2. ViewGroup的measure过程

ViewGroup不仅要完成自身的measure还要去遍历子元素的measure方法。ViewGroup是一个抽象类,不会重写View的onMeasure,但它提供一个measureChildren的方法,这里面去对每个子View进行measure,调用measureChild方法

这里写图片描述

上述方法就是取出子View的LayoutParams,然后通过getChildMeasureSpec来创建子元素的MeasureSpec,接着给子View传入MeasureSpec。

ViewGroup自身的onMeasure各个子类去具体实现。为什么不把每个ViewGroup都统一的onMeasure呢?因为不同的ViewGroup实现细节有很多不同,比如LinearLayout和RelativeLayout就有很多不同。

这里我们做个任务,就是在Activity启动时去获取一个View的宽/高。难处是Activity在启动时onCreate、onStart、onResume中均无法获取View宽/高,不知道measure在什么时候执行完毕,如果没有测完获得的宽高就是0,这里给出四种方法来解决:

(1)Activity/View#onWindowFocusChanged

onWindowFocusChanged方法的含义是View已经初始化完毕,宽高已经准备好了,所以去这里取值没问题。需要注意的是onWindowFocusChanged会调用很多次,比如Activity窗口得到焦点或者失去焦点,onResume和onPause频繁进行就会调用很多次。

(2)view.post(runnable)

通过post可以将一个runnable投递到消息队列的尾部,然后等待Looper调用此runnable的时候,View也准备好了。典型代码如下:

这里写图片描述

(3)ViewTreeObserver

使用ViewTreeObserver的众多回调可以完成这个功能,比如OnGlobalLayoutListener这个接口,当View树发生改变,内部View的可见性发生改变时,OnGlobalLayoutListener就会回调,这是一个取出宽高的好时机

(4)view.measure(int widthMeasureSpec,int heightMeasureSpec)

根据view的LayoutParams来获取宽高

match_parent:直接放弃,因为我们需要知道parentSize即父容器的剩余空间,不知道,所以测不出。

具体数值(px/dp):比如宽高都是100

这里写图片描述

wrap_content:这里写图片描述

这里的(1>>30)-1代表的是specSize是30为组成的,所以最大为30个1即2^30-1就是(1>>30)-1。

关于measure有两种错误的用法,一种是违背了内部的规范,一种不能保证一定能measure出正确的结果:

这里写图片描述

Layout过程

Layout是ViewGroup用来确定子元素的位置,跟measure遍历子元素差不多,但是过程比measure简单。源码就不放了。

Layout首先通过setFrame方法来设定View四个顶点的位置,即初始化mTop、mButton、mRight、mLeft,接着调用onLayout方法,作用是父容器确定子容器的位置。onLayuout的具体实现和布局有关,就是orientation,LinearLayout的onLayout方法如下:

这里写图片描述

再在里面调用setChildeFrame来确定子View的位置,这样全部遍历完子View的layout。而setChildeFrame里面用的实际上是View的测量宽高。

getWidth/getHeight和getMeasureWidth/getMeasureHeight的区别:

View的默认实现中,两者是相等的,只是在不同的时机赋值。但在极端情况(无意义行为)下两者会不一样。

draw过程

draw将view呈现于屏幕,比较简单,遵循以下步骤:

(1)绘制背景 background.draw(canvas)

(2)绘制自己 (onDraw)

(3)绘制Children (dispatchDraw)

(4)绘制装饰 (onDrawScrollBars)

通过源码可以知道View的绘制过程的传递是通过dispatchDraw来实现的

最后

下面是辛苦给大家整理的学习路线,有需要的可以点击这里免费获取

F%95%E6%8B%BF%E9%AB%98%E8%96%AA%EF%BC%81.md)
[外链图片转存中…(img-iR1aZMlB-1644994760470)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值