布局过程,就是程序在运行时利用布局文件的代码来计算出实际尺寸的过程。

布局分为两个阶段:测量阶段和布局阶段。

测量阶段:从上到下递归地调用每个 View 或者 ViewGroup 的 measure() 方法,测量他们的尺寸并计算它们的位置;

布局阶段:从上到下递归地调用每个 View 或者 ViewGroup 的 layout() 方法,把测得的它们的尺寸和位置赋值给它们;

View或ViewGroup的布局过程

  1. 测量阶段,measure() 方法被父 View 调用,在 measure() 中做一些准备和优化工作后,调用 onMeasure() 来进行实际的自我测量。 onMeasure() 做的事,View 和 ViewGroup 不一样:

    1. ViewView 在 onMeasure() 中会计算出自己的尺寸然后保存,保存使用setMeasuredDimension()方法;
    2. ViewGroupViewGroup 在 onMeasure() 中会调用所有子 View 的 measure() 让它们进行自我测量,并根据子 View 计算出的期望尺寸来计算出它们的实际尺寸和位置然后保存。同时,它也会根据子 View 的尺寸和位置来计算出自己的尺寸然后保存;
  2. 布局阶段,layout() 方法被父 View 调用,在 layout() 中它会保存父 View 传进来的自己的位置和尺寸,并且调用 onLayout() 来进行实际的内部布局。onLayout() 做的事, View 和 ViewGroup 也不一样:

    1. View:由于没有子 View,所以 View 的 onLayout() 什么也不做。
    2. ViewGroupViewGroup 在 onLayout() 中会调用自己的所有子 View 的 layout() 方法,把它们的尺寸和位置传给它们,让它们完成自我的内部布局。

重写 onMeasure() 来修改已有的 View 的尺寸具体做法:

  1. 重写 onMeasure() 方法,并在里面调用 super.onMeasure(),触发原有的自我测量;
  2. 在 super.onMeasure() 的下面用 getMeasuredWidth() 和 getMeasuredHeight() 来获取到之前的测量结果,并使用自己的算法,根据测量结果计算出新的结果;
  3. 调用 setMeasuredDimension() 来保存新的结果。

父View的尺寸限制:

  1. 开发者的要求(布局文件中 layout_ 打头的属性)经过父 View 处理计算后的更精确的要求;
  2. 限制的分类: 
    1. UNSPECIFIED:不限制
    2. AT_MOST:限制上限
    3. EXACTLY:限制固定值

重新自定义尺寸的方式:

    1. 重新 onMeasure(),并计算出 View 的尺寸;
    2. 使用 resolveSize() 来让子 View 的计算结果符合父 View 的限制(当然,如果你想用自己的方式来满足父 View 的限制也行)。

自定义view布局过程详解的更多相关文章

  1. Android View 的绘制流程之 Layout 和 Draw 过程详解 (二)

    View 的绘制系列文章: Android View 的绘制流程之 Measure 过程详解 (一) Android View 绘制流程之 DecorView 与 ViewRootImpl 在上一篇  ...

  2. cocos2dx-3.x 导出自定义类到 lua 过程详解

    转载请注明出处:http://www.cnblogs.com/Ray1024 一.简介 最近正在学习cocos2d中的lua游戏开发,因为lua开发的热更新特性,大家开发游戏好像都会优先选择lua作为 ...

  3. 自定义View Draw过程(4)

    目录 目录 1. 知识基础 具体请看我写的另外一篇文章:自定义View基础 - 最易懂的自定义View原理系列 2. draw过程作用 绘制View视图 3. draw过程详解 同measure.la ...

  4. 自定义View Layout过程 (3)

    目录 目录 1. 知识基础 具体请看我写的另外一篇文章:(1)自定义View基础 - 最易懂的自定义View原理系列 2. 作用 计算View视图的位置. 即计算View的四个顶点位置:Left.To ...

  5. 自定义View Measure过程(2)

    目录 目录 1. 作用 测量View的宽/高 在某些情况下,需要多次测量(measure)才能确定View最终的宽/高: 在这种情况下measure过程后得到的宽/高可能是不准确的: 建议在layou ...

  6. Android中mesure过程详解

    我们在编写layout的xml文件时会碰到layout_width和layout_height两个属性,对于这两个属性我们有三种选择:赋值成具体的数值,match_parent或者wrap_conte ...

  7. 自定义View系列教程06--详解View的Touch事件处理

    深入探讨Android异步精髓Handler 站在源码的肩膀上全解Scroller工作机制 Android多分辨率适配框架(1)- 核心基础 Android多分辨率适配框架(2)- 原理剖析 Andr ...

  8. Ubuntu19.04的安装过程详解以及操作系统初始化配置

    Ubuntu19.04的安装过程详解以及操作系统初始化配置                                                                       ...

  9. Spring源码分析之Bean的创建过程详解

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...

随机推荐

  1. OC内存管理总结,清晰明了!

    <span style="font-size:18px;">OC内存管理 一.基本原理 (一)为什么要进行内存管理. 由于移动设备的内存极其有限.所以每一个APP所占的 ...

  2. 机器学习算法中怎样选取超參数:学习速率、正则项系数、minibatch size

    本文是<Neural networks and deep learning>概览 中第三章的一部分,讲机器学习算法中,怎样选取初始的超參数的值.(本文会不断补充) 学习速率(learnin ...

  3. ubuntu下安装phpredis的模块扩展

    1.前提是先安装好redis,然后再安装phpredis. .. 2.先下载phpredis-master.tar.gz安装包... 详细详情例如以下: <span style="co ...

  4. 接口如何使用(以笑话大全api为例)

    接口如何使用(以笑话大全api为例) 一.总结 一句话总结:直接用ajax,或者post,get方式向接口网址请求数据,然后接收网站传过来的数据就好,和我们写网站的时候前台向后台请求数据的方式一样. ...

  5. C# 进制转换 在什么情况下使用16进制,字节数组,字符串

    C# 进制转换 Admin2013年9月18日 名人名言:从工作里爱了生命,就是通彻了生命最深的秘密.——纪伯伦 1.请问c#中如何将十进制数的字符串转化成十六进制数的字符串 //十进制转二进制Con ...

  6. TensorFlow 学习(十五)—— tensorflow.python.platform

    tensorflow.python.platform 下的常用工具类和工具函数:tensorflow/tensorflow/python/platform at master · tensorflow ...

  7. 关于DMA

    用串口在dma中发东西的时候,,, 要判断DMA里是不是由东西,是不是在占用 当多个外设再用DMA的时候,,,要查看DMA有没有占用 一包数没发完,不要再传另一包

  8. [Angular] Using InjectionToken

    Previously we have 'OpaqueToken', but it is DEPRECATED. The new one is called 'InjectionToken'. The ...

  9. iOS开发Quartz2D十二:手势解锁实例

    一:效果如图: 二:代码: #import "ClockView.h" @interface ClockView() /** 存放的都是当前选中的按钮 */ @property ( ...

  10. Delphi 获取Internet缓存文件 -- FindFirstUrlCacheEntry FindNextUrlCacheEntry

    下面是我写的一个函数,把所有的缓存文件路径添加到一个字符串列表中,直接看代码,带了注释.另外还有删除缓存等等大家自己到msdn找找. 需要引用 WinInet // 获取Internet缓存文件 fu ...