简单描述可以解释为:计算大小(measure),布局坐标计算(layout),绘制到屏幕(draw); 下面看看每一步的动作到底是什么, 第一步:当activity启动的时候,触发初始化view过程的是由Window对象的DecorView调用View(具体怎样从xml中读取是用LayoutInflater.from(context).inflate)对象的 public final void measure(int widthMeasureSpec, int heightMeasureSpec)方法开始的,这个方法是final类型的,也就是所有的子类都不能继承该方法,保证android初始化view的原理不变。具体参数类值,后面会介绍。 第二步:View的measure方法 onMeasure(widthMeasureSpec, heightMeasureSpec),该方法进行实质性的view大小计算。注意:view的大小是有父view和自己的大小决定的,而不是单一决定的。这也就是为什么ViewGroup的子类会重新该方法,比如LinearLayout等。因为他们要计算自己和子view的大小。View基类有自己的实现,只是设置大小。其实根据源码来看,measure的过程本质上就是把Match_parent和wrap_content转换为实际大小 第三步:当measure结束时,回到DecorView,计算大小计算好了,那么就开始布局了,开始调用view的 public final void layout(int l, int t, int r, int b),该还是也是final类型的,目的和measure方法一样。layout方法内部会调用onlayout(int l, int t, int r, int b )方法,二ViewGroup将此方法abstract的了,所以我们继承ViewGroup的时候,需要重新该方法。该方法的本质是通过measure计算好的大小,计算出view在屏幕上的坐标点 第四步:measure过了,layout过了,那么就要开始绘制到屏幕上了,所以开始调用view的 public void draw(Canvas canvas)方法,此时方法不是final了,原因是程序员可以自己画,内部会调用ondraw,我们经常需要重写的方法。 以上就是view的大概工作过程,当然了,只是概述,细节多成马了!!!!! 这次主要是跟分析一下measure的过程。下面进入今日主题! ---------------measure的过程! 1. public final void measure(int widthMeasureSpec, int heightMeasureSpec)的参数来源及代表的意思 这个两个参数都是有父view传递过来的,也就是代表了父view的大小。其实说大小不太对,应该说是建议“规格”。他有两部分组成,第一部分:高16位表示MODE,定义在MeasureSpec类中,有三种类型,MeasureSpec.EXACTLY:表示确定大小, MeasureSpec.AT_MOST:表示最大大小, MeasureSpec.UNSPECIFIED:不确定。第二部分:低16位表示size,既父view的大小,这就是为什么,我们在重写onmeasure方法是需要:int specMode = MeasureSpec.getMode(spec); int specSize = MeasureSpec.getSize(spec);这样调用,因为MeasureSpec知道怎么读取。对于跟view(并不是我们在xml中声明的第一个元素),而是系统的Window对象的decorVIew对象。Mode一般都为MeasureSpec.EXACTLY ,而size分别对应屏幕宽,高。也就是Window第一次掉用的view(这个view才是Xml中声明的第一个元素),一般都是这个值,而对于子view来说,这连个值就是你在xml定义的属性 android:layout_width和android:layout_height这个,当然了上面说过view的大小是有父view和子view共同决定的,所以这样有点不对,但是来源于这两个值。意思明白了,我们看看measure里边做什么了 2.measure方法内部操作过程
android:layout_height="200dp" > <TextView android:layout_width="fill_parent" android:layout_height="100dp" android:layout_weight="1" /> <TextView android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" /> </LinearLayout> 上面这个例子再计算第一个TextView的时候,根据android:layout_height="100dp" 值,确定高度为100dp,计算第二个TextView的时候,由于android:layout_height="0"为0,所以不计算其高度,等到计算weight的时候才计算,当计算weight的时候,千万别认为第一个TextView已经计算过了,就不计算了,还是计算的,计算过程如下:第一个分配了100dp,还剩100dp,所以两个textview各分50dp,所以第一个TextVIew的 150dp,第二个就为50dp 至此,view的measure就结束了,所有的view值都结束了,大家可能发现,这个过程只用了几个属性: android:layout_width,android:layout_height,android:layout_weight还有marger和pading,其他的多数属性都在ondraw时候使用, 以上分析全部是自己看源码分析的,有错误之处,欢迎各位指出,以免误导他人。 关于布局(layout),ondraw后续有时间再补上,今天PM给分配任务,得开始干活了,! |
android绘制view的过程之一---------计算view大小(measure)
最新推荐文章于 2021-05-25 23:30:51 发布