View绘制基本知识点

!经过阅读Android开发艺术探索整理html

 
底层工做原理:测量流程、布局流程、绘制流程
 
常见回调方法:构造方法 onAttach onVisiblityChanged onDetach
 
ViewRoot对应ViewRootImpl,链接WindowManager与DecorView的纽带。
performTraversals方法:完成measure、layout、draw流程
 
传递流程:
ViewGroup                                                                    View
1.performMearsure> mearsure>onMearsure  传递        measure     
2.performLayout>layout>onLayout                 传递       layout
3.performDraw>draw>onDraw                      传递        draw
 
解读:performTraversals依次调用performMearsure,performLayout,performDraw分别完成顶层View的measure,layout,draw三大流程。其中performMearsure调用measure,measure调用onMeasure,onMeasure中对全部子元素进行measure过程,此时measure流程由父元素传递到子元素,完成一次measure过程。子元素会重复父元素的measure过程,如此反复完成整个View树遍历。performLayout与performDraw流程相似,可是performDraw的传递过程是 在draw方法中经过dispatchDraw完成
 
方法做用:
measure:决定View的宽高,完成之后经过getMeasuredWidth/getMeasuredHeight获取测量后的宽高,几乎全部状况等同于View的最终宽高,特殊状况除外;
layout:View四个顶点的坐标及实际的View宽、高。四点位置:getTop/getLeft/getRight/getBottom,最终宽高getWidth/getHeight;
draw:决定View 的显示,完成后View才会在屏幕上显示。
 
DectorView:竖直方向包含一个LinearLayout,包含上下两部分,标题栏,内容栏,setContentView布局添加到内容栏,id为content。ViewGroup conent=findViewById(R.android.id.content),获得content;获得咱们设置的View:conent.getChildAt(0);
 
MeasureSpec: 测量规格,32位int值 ,高两位SpecMode 低30位SpecSize。父容器影响View的MeasureSpec建立过程。测量过程当中,系统会将View的LayoutParams根据父容器所施加的规则转换成对应的MeasureSpec,而后再根据MeasureSpec测量View的宽高。
 
SpecMode分类: 
UNSPECIFIED: 不限定大小,通常用于系统内部表示一种测量状态;
AT_MOST:父容器指定大小SpecSize,View不能超过该值,对应wrap_content;
EXACTLY:精确大小,就是SpecSize值,对应match_parent及具体数值
 
MeasureSpec与LayoutParams对应关系:
注意:LayoutParams需和父容器一块儿决定View的MeasureSpec,进一步决定View的宽高
 
DecorView :由窗口尺寸与LayoutParams共同决定
规则:match_parent>EXACTLY,窗口大小
        wrap_content>AT_MOST  大小不定,但不超过窗口
        固定大小,为LayoutParams指定
方法:ViewRootImpl中measureHierarchy方法,屏幕尺寸desireWindowWidth,desireWindowHeight getRootMeaSureSpec方法实现
 
普通View:由父容器MeasureSpec与自身LayoutParams决定,MeasureSpec一旦肯定,onMeasure就能够肯定View的测量宽高
方法:measure以前,经过getChildMeasureSpec获得子元素的MeasureSpec,子元素的MeasureSpec与父元素的MeasureSpec、自己的LayoutParams、padding及margin有关
 
规则:
1.当View固定宽高时,不管父容器何种MeasureSpec,View 的MeasureSpec都精确模式,大小遵循LayoutParams规定大小;
2.View宽高是match_parent时,父容器精确View也精确且大小是父容器剩余空间;父容器最大时View也最大且大小不超过父容器剩余空间
3.View宽高是wrap_content时,无论父容器是精确仍是最大化,View都是最大化且不超过父容器剩余空间。
 
 
 
View工做流程:主要为measure/layout/draw
 
View 的measure:
measure: final方法,调用onMeasure完成。
1.setMeasuredDimension方法设置View宽高测量值。
2.getDefaultSize,AT_MOST与EXACTLY模式时返回的大小就是MeasureSpec中的specSize,最后测量的大小。最终确认在layout阶段,但几乎全部状况下View的测量大小就是最后的大小。
UNSPECFIDED模式,通常用于系统内部测量,宽/高的测量值就是getSuggestedMininumWidth/getSuggestedMininumHeight的返回值。
getSuggestedMininumWidth:若是View没有设置背景,返回android:minWidth的值,能够为0;设置背景,返回android:minWidth和背景宽度中的最大值。
 
结论:直接继承View重写onMeasure并设置wrap_content时的大小,不然在布局中使用的wrap_content至关于match_parent
方式:根据须要,给View指定一个默认的内部宽高,在wrap_content时设置此值,非wrap_content情形,沿用系统的测量值。
 
ViewGroup的measure:
除完成本身的measure,还需遍历调用子元素的measure方法,各子元素递归执行此流程
方法:提供measureChildren方法,对每个子元素measure,经过measureChild方法取出子元素LayoutParams,经过getChildMeasureSpec建立子元素的MeasureSpec,将MeasureSpec传递给子元素的measure来完成测量
ViewGroup没有定义具体的measure过程,由于是抽象类,测量过程的onMeasure须要子类去完成,不一样的子类有不一样的布局特性,测量细节不一样。
 
总结:measure完成后,经过getMeasuredWidth/Heigt就能够正确的获得View的测量 宽高。某些极端状况下:系统须要屡次测量才能肯定宽高,此时onMeasure获取宽高不许确,良好习惯是在onLayout中获取View的测量宽高或最终宽高
 
 
layout:
做用:ViewGroup用来肯定子元素位置
概述:onLayout遍历调用子元素layout,layout中的onLayout方法继续调用
流程:1.setFrame方法设置View的四个顶点位置,顶点位置一旦肯定,View在父容器中的位置就会肯定;
2.调用onLayout,父容器肯定子元素位置,具体实现与具体布局有关,View与ViewGroup没有具体实现
 
View的测量宽高与实际宽高区别:默认实现中是相等的,测量宽高成形于View的measure过程,最终宽高造成于layout过程,两者赋值时机不一样。平常开发中,咱们能够认为测量宽高就等于最终宽高;
注:一些特殊状况下,View会屡次测量才会肯定本身的测量宽高,前几回测量过程当中得出的宽高确实有可能与实际不一致,但最终,两者会相同
 
draw:
流程:1.绘制背景 background.draw(Canvas)
2.绘制本身 onDraw
3.绘制Childrend dispatchDraw
4.绘制装饰onDrawScrollbars
View绘制过程的传递经过dispathcDraw完成,dispatchDraw会遍历调用全部子元素的draw方法,一层一层传递
特殊方法:setWillNotDraw,View默认没有启用,ViewGroup默认启用,不绘制任何内容时,该标记设为true,系统会进行相应优化;对咱们的意义是,当咱们自定义控件继承自ViewGroup,自己不具有绘制功能时,能够开启此标记以便系统优化。明确知道ViewGroup须要经过onDraw绘制时,须要显示关闭此标记
 
自定义View:
分类:
1.继承View重写onDraw :不方便经过布局组合方式,静态或动态显示一些不规则图形,需支持wrap_content,处理padding
2.继承ViewGroup派生特殊Layout:实现自定义布局,当几种View组合在一块儿时,须要合适处理measure与layout过程,同时处理子元素测量布局过程。更接近View底层
3.继承特殊的View如TextView:扩展已有View功能,不须要本身支持wrap_content与padding
4.继承特殊的ViewGroup如LinearLayout:不须要处理measure与layout过程,当几种View组合时。
 
须知:1.让View支持wrap_content
2.若有必要,让View支持padding
3.尽可能不在View中使用Handler,不必。除非明确须要发送消息
4.View中若是有动画或线程,及时中止,detachedFromWindow
5.处理好滑动嵌套冲突
 
思想:首先掌握基本功,如弹性滑动,滑动冲突,绘制原理;面对新的自定义View时可以分类并选择合适的实现思路;平时多积累自定义View的经验,作到融汇贯通
 
转载:http://www.apkbus.com/blog-35555-72610.html
相关文章
相关标签/搜索