Android - View的绘制流程一(measure)
该博文所用的demo结构图:

- <span style="font-family:Microsoft YaHei;">public class MainActivity extends Activity {
- private int desiredWindowWidth;
- private int desiredWindowHeight;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //获取屏幕的宽高,单位为dp
- desiredWindowWidth = Measurement.getScreenWidth(this);
- desiredWindowHeight = Measurement.getScreenHeight(this);
- Log.d("HWGT", "屏幕宽..=.." + desiredWindowWidth + "....屏幕高..=.." + desiredWindowHeight);
- }
- @Override
- protected void onPause() {
- super.onPause();
- //获取状态栏的高度(标题栏+content区域的top坐标)
- Rect frame = new Rect();
- getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
- int statusBarHeight = Measurement.px2dip(this, frame.top);
- //获取 标题栏+content 区域的高度
- int titleAndContentHeight = Measurement.px2dip(this, frame.height());
- //获取content区域的top坐标
- int tempContentTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
- int contentTop = Measurement.px2dip(this, tempContentTop);
- //标题栏的高度 = content区域的top坐标 - 状态栏的高度
- int titleBarHeight = contentTop - statusBarHeight;
- Log.d("HWGT", "titleBarHeight..=.."+titleBarHeight+
- "....contentTop..=.."+contentTop+"....statusBarHeight..=.." + statusBarHeight );
- }
- }</span>
activity_main.xml:
- <span style="font-family:Microsoft YaHei;"><com.hwgt.drawingprocessofview.ui.MyCustomLinearLayoutA
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- tools:context="com.hwgt.drawingprocessofview.MainActivity" >
- <com.hwgt.drawingprocessofview.ui.MyCustomTextViewA
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="13dp"
- android:layout_gravity="center_horizontal"
- android:text="@string/hello_world" />
- <com.hwgt.drawingprocessofview.ui.MyCustomLinearLayoutB
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="13dp">
- <com.hwgt.drawingprocessofview.ui.MyCustomButtonA
- android:layout_width="111dp"
- android:layout_height="wrap_content"
- android:layout_marginLeft="31dp"
- android:text="@string/ok"/>
- </com.hwgt.drawingprocessofview.ui.MyCustomLinearLayoutB>
- </com.hwgt.drawingprocessofview.ui.MyCustomLinearLayoutA></span>
Measurement.java:
- <span style="font-family:Microsoft YaHei;">public class Measurement {
- public static int px2dip(Context context, float pxValue) {
- final float scale = context.getResources().getDisplayMetrics().density;
- return (int) (pxValue / scale + 0.5f);
- }
- public static int getScreenWidth(Context context) {
- WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- DisplayMetrics dm = new DisplayMetrics();
- manager.getDefaultDisplay().getMetrics(dm);
- return px2dip(context, dm.widthPixels);
- }
- public static int getScreenHeight(Context context) {
- WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- DisplayMetrics dm = new DisplayMetrics();
- manager.getDefaultDisplay().getMetrics(dm);
- return px2dip(context, dm.heightPixels);
- }
- }</span>
MyCustomLinearLayoutA.java、MyCustomTextViewA.java、MyCustomLinearLayoutB.java 和 MyCustomButtonA.java类似,构造函数省略了,onMeasure()方法中的处理也一样:
- <span style="font-family:Microsoft YaHei;">public class MyCustomLinearLayoutA extends LinearLayout ... ...
- public class MyCustomTextViewA extends TextView ... ...
- public class MyCustomLinearLayoutB extends LinearLayout ... ...
- public class MyCustomButtonA extends Button {
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- int widthMeasureSpecSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightMeasureSpecSize = MeasureSpec.getSize(heightMeasureSpec);
- Log.d("HWGT", "ButtonA: widthMeasureSpecSize..=.."+Measurement.px2dip(getContext(), widthMeasureSpecSize)
- + "....heightMeasureSpecSize..=.."+Measurement.px2dip(getContext(), heightMeasureSpecSize));
- }
- }</span>
的 setContentView()方法
--> generateDecor()方法创建一个DecorView(FrameLayout的子类)对象 mDecor
该方法主要逻辑为:
和 R.layout.screen_simple
- <span style="font-family:Microsoft YaHei;"><LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:fitsSystemWindows="true">
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="?
android:attr/windowTitleSize"
- style="?android:attr/windowTitleBackgroundStyle">
- <TextView
- android:id="@android:id/title"
- style="?android:attr/windowTitleStyle"
- android:background="@null"
- android:fadingEdge="horizontal"
- android:gravity="center_vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- </FrameLayout>
- <FrameLayout
- android:id="@android:id/content"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:foregroundGravity="fill_horizontal|top"
- android:foreground="?android:attr/windowContentOverlay" />
- </LinearLayout></span>
R.layout.screen_simple:
- <span style="font-family:Microsoft YaHei;"><FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@android:id/content"
- android:fitsSystemWindows="true"
- android:foregroundInsidePadding="false"
- android:foregroundGravity="fill_horizontal|top"
- android:foreground="?android:attr/windowContentOverlay" /> </span>
name="android:windowNoTitle">true</item>时。R.layout.screen_simple将被加入到mDecor中。
布局加入到 mContentParent 中。

紫色框代表根view -- mDecor

(该图截取自Android内核剖析一书,谢谢作者)
- - DecorView開始的
lp.height);
(一般为 MATCH_PARENT)

一个measurespec封装了父视图对子视图在长度或宽度上的要求。一个measurespec由大小和模式组成(使用makeMeasureSpec方法获取)。
UNSPECIFIED:代表父视图对子视图在长度或宽度上不施加不论什么约束。子视图能够是不论什么它想要的大小
(代码经简化,仅为理解大致流程)
measureChildWithMargins(child, ... ... ) 方法(定义在ViewGroup类中)
—— 向mDecor里加入的窗体布局(图一中为R.layout.screen_simple,图二中为R.layout.screen_title)的measure方法得到运行,再在R.layout.screen_simple或R.layout.screen_title的onMeasure方法中进行遍历,运行到id为content的布局相应的measure方法,...
... ,直到该博文demo中的MyCustomLinearLayoutA的measure和onMeasure方法。

- <span style="font-family:Microsoft YaHei;">protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (mOrientation == VERTICAL) {
- measureVertical(widthMeasureSpec, heightMeasureSpec);
- } else {
- measureHorizontal(widthMeasureSpec, heightMeasureSpec);
- }
- }</span>
{
== 0 ? mTotalLength : 0 。这里跳过了weight>0的子视图。所以值为mTotalLength(在对MyCustomTextViewA进行measure时。值为0。另外,測量的是竖直方向。所以第4个參数直接传入0)
i, widthMeasureSpec, 0, heightMeasureSpec,totalWeight == 0 ? mTotalLength : 0);
heightMeasureSpec,int totalHeight) {
int widthUsed,
即 MyCustomTextViewA 的布局參数
— id为content的布局传递来的WidthMeasureSpec
和 MeasureSpec.getMode 得到对应的size和mode(360dp MeasureSpec.EXACTLY)
这三项进行相加
的本身尺寸之外 全部空间的总和
第三个參数:child的width值(childHeightMeasureSpec 同理)
的本身尺寸之外 全部空间的总和
的 MeasureSpec
改为"wrap_content"或详细的一个dp值
和 mMeasuredHeight 的过程。
— draw了。
Android - View的绘制流程一(measure)的更多相关文章
- Android View的绘制流程
写得太好了,本来还想自己写的,奈何肚里墨水有限,直接转吧.正所谓前人种树,后人乘凉.. View的绘制和事件处理是两个重要的主题,上一篇<图解 Android事件分发机制>已经把事件的分发 ...
- android view的 绘制流程
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 首先是 从 视图根 这个类的 进行遍历 performTraversals 方法 开 ...
- Android View 的绘制流程之 Layout 和 Draw 过程详解 (二)
View 的绘制系列文章: Android View 的绘制流程之 Measure 过程详解 (一) Android View 绘制流程之 DecorView 与 ViewRootImpl 在上一篇 ...
- 每日一问:简述 View 的绘制流程
Android 开发中经常需要用一些自定义 View 去满足产品和设计的脑洞,所以 View 的绘制流程至关重要.网上目前有非常多这方面的资料,但最好的方式还是直接跟着源码进行解读,每日一问系列一直追 ...
- 深入理解 Android 之 View 的绘制流程
概述 本篇文章会从源码(基于Android 6.0)角度分析Android中View的绘制流程,侧重于对整体流程的分析,对一些难以理解的点加以重点阐述,目的是把View绘制的整个流程把握好,而对于特定 ...
- Android探究之View的绘制流程
Android中Activity是作为应用程序的载体存在,代表着一个完整的用户界面,提供了一个窗口来绘制各种视图,当Activity启动时,我们会通过setContentView方法来设置一个内容视图 ...
- Android的自定义View及View的绘制流程
目标:实现Android中的自定义View,为理清楚Android中的View绘制流程“铺路”. 想法很简单:从一个简单例子着手开始编写自定义View,对ViewGroup.View类中与绘制View ...
- 【转】深入理解Android之View的绘制流程
概述 本篇文章会从源码(基于Android 6.0)角度分析Android中View的绘制流程,侧重于对整体流程的分析,对一些难以理解的点加以重点阐述,目的是把View绘制的整个流程把握好,而对于特定 ...
- Android之View的绘制流程
本篇文章会从源码(基于Android 6.0)角度分析Android中View的绘制流程,侧重于对整体流程的分析,对一些难以理解的点加以重点阐述,目的是把View绘制的整个流程把握好,而对于特定实现细 ...
- Android View的绘制机制流程深入详解(四)
本系列文章主要着重深入介绍Android View的绘制机制及流程,第四篇主要介绍Android自定义View及ViewGroup的实现方法和流程. 主要介绍了自绘控件.自定义组合控件.自定义继承控件 ...
随机推荐
- 送你一套纯净版的 SSM 架构
大致介绍一下,目前 Java 中使用比较多的框架组合就是 Spring .Springmvc .Mybatis ,这 3 个框架也就是我们常说的 SSM. 前面陆陆续续也已经介绍完了这 3 个框架,今 ...
- Android View事件分发-从源码分析
View事件分发-从源码分析 学习自 <Android开发艺术探索> https://blog.csdn.net/qian520ao/article/details/78555397?lo ...
- 表达式括号匹配(stack.cpp)
[问题描述] 假设一个表达式有英文字母(小写).运算符(+,—,*,/)和左右小(圆)括号构成,以“@”作为表达式的结束符.请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回 ...
- 格式化p6spy的输出日志
众所周知, p6spy打印出来的日志是一行很长很长的内容, 很不容易查看, 牛B的p6spy为什么就不能想hibernate那样有format_sql的功能? 竟然没有, 我只好自己动手写一个日志输出 ...
- JavaScript学习笔记[0]
JavaScript学习笔记[0] 使用的是廖雪峰JavaScript教程. 数据类型 Number 表示数字,不区分浮点整形. === 比较时不转化数据类型. == 反之. NaN与任何值都不想等, ...
- Hadoop系列之(二):Hadoop集群部署
1. Hadoop集群介绍 Hadoop集群部署,就是以Cluster mode方式进行部署. Hadoop的节点构成如下: HDFS daemon: NameNode, SecondaryName ...
- C# 读带复选框的excel,写excel并设置字体、边框、背景色
这是一篇excel读写功能大汇总,通过C#调用Microsoft.Office.Interop.Excel.dll才能完成任何复杂格式excel的读写操作. 本文需要读取的excel格式如下: 可见表 ...
- 在Ubuntu的系统中怎样将应用程序加入到開始菜单中
/********************************************************************* * Author : Samson * Date ...
- NXP LPC-Link LPC3154
LPC-Link: LPC-Link调试探针由恩智浦.Code Red和Embedded Artists三方共同开发, 该探针可与目标板断开,利用板载10针JTAG/SWD连接器直接用于客户自己的设计 ...
- What is OpenOCD?
About OpenOCD was created by Dominic Rath as part of a 2005 diploma thesis written at the University ...
