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

 
底层工作原理:测量流程、布局流程、绘制流程
 
常见回调方法:构造方法 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

View绘制基本知识点的更多相关文章

  1. 3.View绘制分析笔记之onLayout

    上一篇文章我们了解了View的onMeasure,那么今天我们继续来学习Android View绘制三部曲的第二步,onLayout,布局. ViewRootImpl#performLayout pr ...

  2. View绘制详解(五),draw方法细节详解之View的滚动/滑动问题

    关于View绘制系列的文章已经完成了四篇了,前面四篇文章主要带小伙伴们熟悉一下View的体系的整体框架.View的测量以及布局等过程,从本篇博客开始,我们就来看看View的绘制过程.View的绘制涉及 ...

  3. View绘制详解(三),扒一扒View的测量过程

    所有东西都是难者不会,会者不难,Android开发中有很多小伙伴觉得自定义View和事件分发或者Binder机制等是难点,其实不然,如果静下心来花点时间把这几个技术点都研究一遍,你会发现其实这些东西都 ...

  4. 【朝花夕拾】Android自定义View篇之(一)View绘制流程

    前言 转载请申明转自[https://www.cnblogs.com/andy-songwei/p/10955062.html]谢谢! 自定义View.多线程.网络,被认为是Android开发者必须牢 ...

  5. View绘制机制

    View 绘制机制 1. View 树的绘图流程 当 Activity 接收到焦点的时候,它会被请求绘制布局,该请求由 Android framework 处理.绘制是从根节点开始,对布局树进行 me ...

  6. 4.View绘制分析笔记之onDraw

    上一篇文章我们了解了View的onLayout,那么今天我们来学习Android View绘制三部曲的最后一步,onDraw,绘制. ViewRootImpl#performDraw private ...

  7. 2.View绘制分析笔记之onMeasure

    今天主要学习记录一下Android View绘制三部曲的第一步,onMeasure,测量. 起源 在Activity中,所有的View都是DecorView的子View,然后DecorView又是被V ...

  8. 1.Android 视图及View绘制分析笔记之setContentView

    自从1983年第一台图形用户界面的个人电脑问世以来,几乎所有的PC操作系统都支持可视化操作,Android也不例外.对于所有Android Developer来说,我们接触最多的控件就是View.通常 ...

  9. Android应用层View绘制流程与源码分析

    1  背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原 ...

随机推荐

  1. 获取Oracle数据库awr报告方法

    --登录数据库  sqlplus username/passwd; --运行生成AWR报告脚本  SQL> @?/rdbms/admin/awrrpt.sql; --输入要生成报告的格式:htm ...

  2. Python的数据类型3元组,集合和字典

    首先要讲到的就是元组 元组其实拥有列表的一些特性,可以存储不同类型的值,但在某些方面元组又比不上列表 定义一个元组,你可以不用加‘ [ ] ’,你只需用逗号隔开即可 例如 1 2 3 4 5 6 7 ...

  3. uart boot log

    CC开始 xmodem 传输. 按 Ctrl+C 取消. 100% 95 KB 4 KB/s 00:00:23 0 Errors U-Boot SPL 2018.01 (Jan 16 2019 - 1 ...

  4. bzoj1086

    题解: 树分块 每一次当个数大于B的时候分成一块 省会城市为当前子树根 然后最后剩下的节点和前一个分为一块 代码: #include<bits/stdc++.h> using namesp ...

  5. Active MQ的初步探索

    参考链接: http://blog.csdn.net/jiuqiyuliang/article/details/46701559 JMS是jee规范,active MQ是该规范的实现 Active M ...

  6. (转)git合并多个commit

    原文地址:http://platinhom.github.io/2016/01/02/git-combine_commit/ 有时commit多了看着会不爽.所以想合并掉一些commit. 这里是最简 ...

  7. Installing MIB in Ubuntu and Solving the Error “SNMP Cannot Find Module …”

    Has noticed an error after executing the command snmpwalk with the indication of MIB instead of OID: ...

  8. websevice之三要素

    SOAP(Simple Object Access Protocol).WSDL(WebServicesDescriptionLanguage).UDDI(UniversalDescriptionDi ...

  9. gulp 系统教程

    移步: http://www.cnblogs.com/2050/p/4198792.html gulp外挂 加md5   版本号 自动合并图片并修改css的坐标 一个系统列子 gulp可以做哪些事情

  10. header 输出原始的php报头文件

    header() 函数向客户端发送原始的 HTTP 报头. 认识到一点很重要,即必须在任何实际的输出被发送之前调用 header() 函数 (在 PHP 4 以及更高的版本中,您可以使用输出缓存来解决 ...