前言

  上一篇blog中,了解到measure过程对View进行了测量,得到measuredWidth/measuredHeight。对于ViewGroup,则计算出全部children的宽高进行求和。本篇来分析一下layout过程。

layout综述

  layout方法对一个View及它的后代分配size与position,是View绘制过程的第二步(the second phase of layout mechanism),其中用到了上一步measure出的宽高。与measure-onMeasure相似,layout中也是回调了onLayout方法。但有一点不一样,layout并没有被声明为final。

  子View在继承后,不应当重写onLayout;当子View是一个ViewGroup时,需要重写onLayout,对该ViewGroup下面的每一个View调用layout。

  layout四个参数l, t, r, b分别表示相对于ParentView的距离,最常见的传参就是(0, 0, width, height)。

    public void layout(int l, int t, int r, int b) {
if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
} int oldL = mLeft;
int oldT = mTop;
int oldB = mBottom;
int oldR = mRight; boolean changed = isLayoutModeOptical(mParent) ?
setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b); if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
onLayout(changed, l, t, r, b);
mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED; ListenerInfo li = mListenerInfo;
if (li != null && li.mOnLayoutChangeListeners != null) {
ArrayList<OnLayoutChangeListener> listenersCopy =
(ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
int numListeners = listenersCopy.size();
for (int i = 0; i < numListeners; ++i) {
listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
}
}
} mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
}

  layout方法中,首先根据标志位判断是否需要重新measure,随后对是否为optical进行判断,这个参数用来控制投影等效果,通常情况下直接进入setFrame,setFrame判断视图大小是否发生了变化,以确定有没有必要进行重绘。

  随后回调onLayout,在View中,onLayout是个空壳,什么都没有做;在ViewGroup中则依次对子View调用layout。

  如果layout有变化,则通知所有注册的Listener变化前后的layout数值。

setFrame

  当size和position变化时,返回true。如果发生了变化,会在setFrame方法内部调用invalidate。

onLayout

  View中onLayout什么都没有做,在ViewGroup中,根据各自实际规则(Linear、Relative 等)对内部Views进行布局安排。

getMeasuredWidth与getWidth

  • 可以调用的时机不同:getMeasuredWidth在measure后即可调用,getWidth要在layout后才可以调用。(在发生时机之前调用的话均返回0)
  • 含义不同:getMeasuredWidth是View计算出自己的实际大小,getWidth是在布局后的大小。最简单的,在ScrollLayout中,getHeight返回屏幕内的高度,getMeasuredHeight返回屏幕内+屏幕外的总高度。

小结

  这一篇比较简单,因为大部分情况下,都不需要重写onLayout方法;一旦重写该方法(ViewGroup),就会发现要做的事情还是很多的,参见LinearLayout.onLayout、RelativeLayout.onLayout。

  下一篇着手onDraw()。

Android UI 绘制过程浅析(三)layout过程的更多相关文章

  1. Android UI 绘制过程浅析(五)自定义View

    前言 这已经是Android UI 绘制过程浅析系列文章的第五篇了,不出意外的话也是最后一篇.再次声明一下,这一系列文章,是我在拜读了csdn大牛郭霖的博客文章<带你一步步深入了解View> ...

  2. Android UI 绘制过程浅析(一)LayoutInflater简介

    前言 这篇blog是我在阅读过csdn大牛郭霖的<带你一步步深入了解View>一系列文章后,亲身实践并做出的小结.作为有志向的前端开发工程师,怎么可以不搞懂View绘制的基本原理——简直就 ...

  3. Android UI 绘制过程浅析(四)draw过程

    前言 draw是绘制View三个步骤中的最后一步.同measure.layout一样,通常不对draw本身进行重写,draw内部会调用onDraw方法,子类View需要重写onDraw(Canvas) ...

  4. Android UI 绘制过程浅析(二)onMeasure过程

    前言 View的绘制过程分为 measure.layout.draw三个步骤,接下来对这三个步骤逐一进行研究. measure方法的签名 public final void measure(int w ...

  5. Android UI绘制流程及原理

    一.绘制流程源码路径 1.Activity加载ViewRootImpl ActivityThread.handleResumeActivity() --> WindowManagerImpl.a ...

  6. 自己定义View Layout过程 - 最易懂的自己定义View原理系列(3)

    前言 自己定义View是Android开发人员必须了解的基础 网上有大量关于自己定义View原理的文章.但存在一些问题:内容不全.思路不清晰.无源代码分析.简单问题复杂化等等 今天,我将全面总结自己定 ...

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

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

  8. Android UI(一)Layout 背景局部Shape圆角设计

    Jeff Lee blog:   http://www.cnblogs.com/Alandre/  (泥沙砖瓦浆木匠),retain the url when reproduced ! Thanks ...

  9. 简单研究Android View绘制一 测量过程

    2015-07-27 16:52:58 一.如何通过继承ViewGroup来实现自定义View?首先得搞清楚Android时如何绘制View的,参考Android官方文档:How Android Dr ...

随机推荐

  1. hdu 1039 (string process, fgets, scanf, neat utilization of switch clause) 分类: hdoj 2015-06-16 22:15 38人阅读 评论(0) 收藏

    (string process, fgets, scanf, neat utilization of switch clause) simple problem, simple code. #incl ...

  2. 新手入门之GDB调试

    写这篇文章算是对最近两天工作的一个经验总结吧. 要让可执行文件比较方便地在DGB上调试,在用gcc编译的时候要使用-g选项. 如何使用GDB启动被调试程序? "gdb path_to_deb ...

  3. Win7下通过eclipse远程连接CDH集群来执行相应的程序以及错误说明

    最近尝试这用用eclipse连接CDH的集群,由于之前尝试过很多次都没连上,有一次发现Cloudera Manager是将连接的端口修改了,所以才导致连接不上CDH的集群,之前Apache hadoo ...

  4. 10-20日 && 抽签问题

    Ants # include <cstdio> #include <algorithm> ; int L, n, x[MAX_N]; void solve() { ; ; i ...

  5. UIImageView变灰

    1.UIImageView圆角 CALayer *l = [cell.imgAvatarImage layer]; [l setMasksToBounds:YES]; [l setCornerRadi ...

  6. windows环境下XAMPP安装、多域名多端口配置、与python环境并存

    一.去xampp官网下载最新版本的安装包,安装一般软件的安装步骤,一直下一步,不过如果你想安装到指定目录中的话,在选择安装位置的时候设置想要安装的位置. 二.我们在工作中经常遇到同时调试多个网站的情况 ...

  7. echo、print、sprint、sprintf输出

    echo() 函数 定义和用法 echo() 函数输出一个或多个字符串. 语法 echo(strings) 参数 描述 strings 必需.一个或多个要发送到输出的字符串. 提示和注释 注释:ech ...

  8. Hive 实战(2)--hive分区分桶实战

    前言: 互联网应用, 当Mysql单机遇到性能瓶颈时, 往往采用的优化策略是分库分表. 由于互联网应用普遍的弱事务性, 这种优化效果非常的显著.而Hive作为数据仓库, 当数据量达到一定数量时, 查询 ...

  9. asp.net 把图片压缩成zip之后再进行下载

    //这是导出的js方法 function fundaochu() { var data = "keyword=GetImageListdaochu&type=daochu&m ...

  10. 9.9,新iPhone要来了,是欢呼,还是墙角画圈,一会儿见分晓