View的工作原理

来源:互联网 发布:ubuntu 命令界面 乱码 编辑:程序博客网 时间:2024/06/05 21:04

ViewRoot:

ViewRoot应用于ViewRootImpl类,它是连接WindowManager和DecorView的枢纽,View的三大流程都是通过ViewRoot来完成的

三大流程:测量measure、布局layout、draw绘制

从ViewRoot的performTraversals方法开始的,经过3大流程将一个view绘制出来



顶级view--DecorView:

本身就是一个FrameLayout,包含一个竖直方向的LinearLayout,而linearLayout又包含内容栏和标题栏,其中内容栏也是一个FrameLayout,它的id是content,通过他的方法getChildAt(0)就可以获得我们的view



Measure:

MeasureSpec,测量说明书,很大程度上决定了一个View的尺寸规格

在测量的过程中,系统会将View的LayoutParams根据父容器所施加的规则转换成对应的MeasureSpec,然后根据这个进行测量

MeasureSpec的2个参数,SpecMode和SpecSize,一组SpecMode和SpecSize就可以打包为一个MeasureSpec,相反解包也可以获得参数

SpecMode有三类:UNSPECIFIED不限制型、EXACTLY精准型(对应match_parent和数值型)、AT_MOST(对应wrap_content)

需要注意的是,MeasureSpec是由LayoutParams、margin、padding和父容器一起决定的,其中顶级View父容器没有,由窗口尺寸决定

LayoutParams也有3种模式:MATCH_PARENT、WRAP_CONTENT、固定值模式

View的MeasureSpec的创建规则如下表:


在测量阶段,用getMeasuredWidth/Height来获得测量宽高,基本和layout中使用getWidth/Height的实际宽高是一样的


*直接继承自View,需要重写onMeasure方法并且设置wrap_content的自身大小,否则wrap_content不能正常工作,它和match_parent效果一样,设置的方法如下:


如果在活动中需要获得自定view的属性值,由于它和活动的生命周期不同,所以可能会获取失败,可以有一些方法解决:

onWindowFocusChanged,焦点,这个方法在变成焦点和失去焦点时会被调用,此时view已经绘画完了,因此可以在这里获得准确的属性

使用view自身带有的post方法(尽量不要使用Handler),将一个Runnable传递进去,在消息队列里放置消息,然后在Runnable里执行获得属性的操作

使用ViewTreeObserver

使用view.measure手动对View进行测量


Layout:

作用是ViewGroup用来确定子元素的位置

在测量阶段,用getMeasuredWidth/Height来获得测量宽高,基本和layout中使用getWidth/Height的实际宽高是一样的
Layout阶段用来确定view的位置,也就是四个顶点和实际宽高


Draw:

过程:

绘制背景background.draw(canvas)

绘制自己onDraw

绘制children(dispatchDraw)(通过dispatchDraw来实现)

绘制装饰(onDrawScrollBars)


自定义View:

分类:

继承自View重写Draw:需要自己支持wrap_content和处理padding

继承自ViewGroup派生的特殊的Layout:需要合适地处理ViewGroup的测量、布局过程,同时需要处理子元素的测量和布局过程

继承自特定的View

继承自特定的ViewGroup

需要注意的是,如果View中有线程或者动画,需要及时停止

另外,我们在继承自View时,类名是XML中的标签名,类似Button这个名称一样,所以还要为View制定id


自定义属性:
第一步,在values下创建自定义属性XML


第二步,在View的构造方法中,对自定义属性的值进行解析,然后处理


第三步,在布局文件中使用自定义属性


app就是自定义属性的前缀


自定义View的思想:

1.     掌握基本功,比如View的弹性滑动、滑动冲突、绘制原理

2.     能够对其进行分类并选择合适的实现思路


原创粉丝点击