!通过阅读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的测量宽高或最终宽高
作用: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
- 3.View绘制分析笔记之onLayout
上一篇文章我们了解了View的onMeasure,那么今天我们继续来学习Android View绘制三部曲的第二步,onLayout,布局. ViewRootImpl#performLayout pr ...
- View绘制详解(五),draw方法细节详解之View的滚动/滑动问题
关于View绘制系列的文章已经完成了四篇了,前面四篇文章主要带小伙伴们熟悉一下View的体系的整体框架.View的测量以及布局等过程,从本篇博客开始,我们就来看看View的绘制过程.View的绘制涉及 ...
- View绘制详解(三),扒一扒View的测量过程
所有东西都是难者不会,会者不难,Android开发中有很多小伙伴觉得自定义View和事件分发或者Binder机制等是难点,其实不然,如果静下心来花点时间把这几个技术点都研究一遍,你会发现其实这些东西都 ...
- 【朝花夕拾】Android自定义View篇之(一)View绘制流程
前言 转载请申明转自[https://www.cnblogs.com/andy-songwei/p/10955062.html]谢谢! 自定义View.多线程.网络,被认为是Android开发者必须牢 ...
- View绘制机制
View 绘制机制 1. View 树的绘图流程 当 Activity 接收到焦点的时候,它会被请求绘制布局,该请求由 Android framework 处理.绘制是从根节点开始,对布局树进行 me ...
- 4.View绘制分析笔记之onDraw
上一篇文章我们了解了View的onLayout,那么今天我们来学习Android View绘制三部曲的最后一步,onDraw,绘制. ViewRootImpl#performDraw private ...
- 2.View绘制分析笔记之onMeasure
今天主要学习记录一下Android View绘制三部曲的第一步,onMeasure,测量. 起源 在Activity中,所有的View都是DecorView的子View,然后DecorView又是被V ...
- 1.Android 视图及View绘制分析笔记之setContentView
自从1983年第一台图形用户界面的个人电脑问世以来,几乎所有的PC操作系统都支持可视化操作,Android也不例外.对于所有Android Developer来说,我们接触最多的控件就是View.通常 ...
- Android应用层View绘制流程与源码分析
1 背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原 ...
随机推荐
- Linux文件与目录管理(三)
一.Linux文件内容查看 1.cat:由第一行开始显示文件内容 2.tac:从最后一行开始显示,可以看出tac是cat倒着写 3.nl:显示的时候,顺便输出行号 4.more:一页一页的显示文件内容 ...
- CNN autoencoder 进行异常检测——TODO,使用keras进行测试
https://sefiks.com/2018/03/23/convolutional-autoencoder-clustering-images-with-neural-networks/ http ...
- 快速切题 acdream手速赛(6)A-C
Sudoku Checker Time Limit: 2000/1000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) Submi ...
- 第一章连通性问题-----algorithm in C 读书笔记
首先不得不吐槽一下翻译的质量,霍红卫....你给我站出来,不打死你,只想问你一下,你当年四级过了吗? 问题描述 输入两个整数,代表两个节点,如果这两个整数没有建立连接(这包括直接连接和通过其他节点连接 ...
- (翻译)Angular 1.3中的验证器管道
原文地址:VALIDATORS PIPELINE IN ANGULAR 1.3 我们知道在Angular中操作表单是很爽的.因为Angular本身的作用域模型,我们总能在相应的作用域中获取到表单当前的 ...
- 2019.1.11 EDVT
Processing Gain and Occupied Bandwidth ESA Basic Setup (11b)Span 110MHzRBW 100kHzVBW 100kHzSweep Tim ...
- avalonJS-源码阅读(2)
上一篇文章讲述的avalon刷页面所用到的几个函数. 这篇则是主要讲avalon 对刷DOM刷出来的avalon自定义属性如何处理的. 目录[-] avalon页面处理(2)数据结构解析avalon标 ...
- IOS的各种控件(转载,防止遗忘)
UITextView控件的详细讲解 感觉写的相当不错,而且很全就直接转载了 1.创建并初始化 创建UITextView的文件,并在.h文件中写入如下代码: #import <UIKit/UIKi ...
- Ubuntu 12.04硬盘安装教程
从服务器下载Ubuntu 12.04光盘镜像文件到 C 盘.下载地址:\\192.167.100.225\share\Tool\Ubuntu\ubuntu-12.04.1-desktop-amd64. ...
- Linux C 数据结构->双向链表(阴阳在六,何以言九~)
0. 弄完了单链表,在看双向链表.怎么整?多写,多想,想不通画出来在想,再写,再模仿~ 1. 没啥说的,敲代码~ 说点啥呢,注意自己的代码风格哦,要符合"潮流",不要独树一帜 ...