View Measure Layoout Draw

来源:互联网 发布:指南针2017软件骗局 编辑:程序博客网 时间:2024/06/14 01:34

measure过程决定了View的宽度和高度,Measure完成之后,可以通过getMeasureWidth和getMeasureHeight得到View的宽度和高度,一般情况下它都等于View的最终的宽高。

在测量的过程中,系统会将View的lauoutParams根据父VIew所施加的规则转换对应的MeasueSpec,然后在根据这个measureSpec来测量View的宽度和高度,该测量的宽和和高度只是测量的宽度和高度,不一定等于View的最终的宽度和高度。


一般q情况下View,其MeasureSpec有父View和自身的LayoutParams来共同决定

当View采用固定的宽度和高度的时候,不管父View的MeasureSpec是什么,View的最终MeasureSpec都是精确的模式,且大小遵循LayputParams中的大小。

当View的宽度和高度是match_parent时,如果父View是精确模式,那么View也是精确模式 并且大小是父View的剩余空间;如果父View是at_most模式,那么View也是at_most模式 且大小不会超过父容器的剩余空间。

当View的宽和高是wrap_content时,不管父View的模式是精确模式还是最大化,View的模式总是最大化 且大小不能超过父容器的剩余空间。


SpecMode

UNSPECIFIED

    父容器不对View施加限制,view需要多大就给多大,这种情况一般用在系统内部,表示一种测量状态。

EXACTLY

    父容器已经检测出View所需要的精确大小,这种情况下,View的大小最终就是SpecSize所指定的大小,它对应与LayoutParams中的match_parent和具体的数值

AT_MOST

    父容器指定了一个可用的大小即SpecSize,View的大小不能大于这个值,对应与Layoutparams中的wrap_content


void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

widthMeasureSpec、heightMeasureSpec是由父View传递进来的,其值是由父View的MeasureSpec和子View的lauoutParams共同决定的。

是由父View计算完成后 传递进来的。


view的MeasureWidth和MeasureHeight形成于measure过程中
view的最终width和height形成于layout过程中,通常这两个者是一样的,但是如果重写了layout方法就不一定相等了。


直接继承View的自定义控件需要重写onmeasure方法,并且设置wrap_content时的自身大小,否则在
布局中使用warp_content时 就相当于使用match_parent。因为在布局中使用wrap_content的时候,view的
SpecMode就是AT_MOST模式,在这种模式下,它的宽度和高度等于SpecSize,这种情况下View的SpecSize就是parentSize
,而parentSize是父View的目前可以使用的大小,也就是父View当前剩余的控件大小。很显然,View的宽和高就等于父
View当前剩余的控件大小,这种效果和在布局中使用match_parent完全一致。
处理模版代码:

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);    int widthSpecsize = MeasureSpec.getSize(widthMeasureSpec);    int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);    int heightSpecSize = MeasureSpec.getMode(heightMeasureSpec);    if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {        setMeasuredDimension(mWidth/*自定义控件的宽度大小*/, mHeight/*自定义控件高度大小*/);    } else if (widthSpecMode == MeasureSpec.AT_MOST) {        setMeasuredDimension(mWidth/*自定义控件的宽度大小*/, heightSpecSize);    } else if (heightSpecMode == MeasureSpec.AT_MOST) {        setMeasuredDimension(widthSpecsize, mHeight/*自定义控件高度大小*/);    }}


layout过程决定了View的四个顶点的坐标和实际的宽高【横坐标相减=宽度,纵坐标相减=高度】,layout完成之后,可以通过getTop,getBottom,getLeft,getRight来拿到View的

四个顶点的坐标,同时可以通过getWidth和getHight得到View的最终的宽度和高度。


draw过程决定了View的显示,draw完成之后 View才会显示在屏幕上


draw绘制过程:
1、绘制背景 background.draw(canvas)
2、绘制自身的内容 onDraw
3、绘制child (dispatchDraw)
4、绘制装饰




在自定义View的时候,如果是继承View实现的,那么如果不对View的wrap_content做处理,就相当于使用match_parent.
同时需要注意自己需要处理View的padding属性值。




图片转载:

自定义View分类:



自定义View须知:



原创粉丝点击