前言

  上一篇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. 关于ADDED_TO_STAGE事件

    可视类初始化的时候,很多时候要用到stage属性,则要使用Event.ADDED_TO_STAGE事件,这个swf被其它的文件加载,如果直接在初始化函数内使用stage属性 .但是,文档类初始化函数内 ...

  2. Android GridView的使用

    Android的GridView控件用于把一系列的空间组织成一个二维的网格显示出来应用的比较多的就是组合图片显示下面我就详细讲一个例子 首先写一个类继承BaseAdapter 1. Java代码 1 ...

  3. 初用Ubuntu常见问题及解决方案之一

    1.我的Vaio Fit15e的无线网卡是BCM43142,装了Ubuntu后为了装驱动折腾了好久,因为这款网卡在Broadcom官网都找不到驱动,google了一大圈,一个最简单的命令可以解决这个问 ...

  4. android技巧(二)listview的优化

    对于listview的优化有以下三个措施: 1.原有listview每一个item显示时都会调用一次getView()方法,实际上对于ListView而言,只需要保留能够显示的最大个数的view即可, ...

  5. SVD小结

    1.矩阵分解 假设一个矩阵Data是m行n列,SVD(奇异值分解)将Data分解为U,E,VT 三个矩阵: Datam*n=Um*kEk*kVTk*n E是一个对角矩阵,对角元素为奇异值,对应Data ...

  6. angularjs中展示富文本编辑器文本,向DOM中插入元素

    前几天在用textangular富文本编辑器插件时,将存储的文本及格式存储到数据库中,但是从后台接口中再向angular页面插入时却不能执行,即在Angular中操作DOM没有实现,后来查看了一下,操 ...

  7. asp.net 发布后,遇到的导出excel报错的问题

    做的asp.net程序,最近要发布在外网上,发布过程不太难,网上都有现成的,只要按照相应的步骤基本都不会有什么问题,关键是发布成功后,程序中涉及到excel的导出或者导入问题,就会提示“检索COM 类 ...

  8. Android GPS定位 获取经纬度

    移动 是手机与手持设备的最大特点,可以通过Eclipse的DDMS视图,模拟设备的位置变化,改变经纬度后,点击send,然后运行程序,在应用程序中,动态的获取设备位置,然后显示当前的位置信息. 获取位 ...

  9. Context的使用(转)

    1.Context概念 Context,相信不管是第一天开发Android,还是开发Android的各种老鸟,对于Context的使用一定不陌生~~你在加载资源.启动一个新的Activity.获取系统 ...

  10. 无锁队列以及ABA问题

    队列是我们非常常用的数据结构,用来提供数据的写入和读取功能,而且通常在不同线程之间作为数据通信的桥梁.不过在将无锁队列的算法之前,需要先了解一下CAS(compare and swap)的原理.由于多 ...