前言

  上一篇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. Yii2 主从 数据库

    配置方法 参考资料:http://www.linuxidc.com/Linux/2015-07/120134.htm 读写分离(Read/Write Splitting). 1.原理:让主数据库(ma ...

  2. css3 弹框提示样式

    .common-dialog-box{ opacity: 0; filter: alpha(opacity=0); position: fixed; top: 0%; left: 50%; z-ind ...

  3. php大力力 [038节] 全栈工程师的含义

    管理时间 http://www.nowamagic.net/librarys/eight/posts/2753 从知乎上看到“全栈开发者”讨论之后的自黑 什么是全栈开发者 https://beeclo ...

  4. IOS开发-当遇到tableView整体上移时的解决方案

    方案一在使用了navigationController后,当界面进行跳转往返后,时而会出现tableView上移的情况,通常会自动上移64个像素,那么这种情况,我们可以关闭tableView的自动适配 ...

  5. Polymer.js

    Polymer 1.0 教程 安装 bower install --save Polymer/polymer

  6. Python 基礎 - for流程判斷

    今天介紹另一個循環判斷式 for循環,首先,先寫一個很簡單的 for循環的代碼 #!/usr/bin/env python3 # -*- coding:utf-8 -*- for i in range ...

  7. pull方法解析xml

    private void getData() {        new Thread() { public void run() {                try {              ...

  8. MFC 线程使用

    CWinThread*  m_pthread; //多线程对象 struct param//参数传递结构体 { int id; TASK t[20]; }; CNB400Dlg::CNB400Dlg( ...

  9. python unicode字节串转成中文问题

    如题,其实我的问题很简单,就是在写爬虫的时候拿到网页的信息包含类似“\u65b0\u6d6a\u5fae\u535a\u6ce8\u518c”的字符串,实际上这是unicode的中文编码,对应的中文为 ...

  10. intelij idea 2016.2注册码

    激活码: 43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1l ...