前言

前几天被问到了getMeasuredWidthgetWidth之间的区别,因此回来看了一下源码,又顺便复习了一遍measure/layout/draw的过程,有兴趣的同学可以看前面的几篇文章

  • View 绘制体系知识梳理(3) - 绘制流程之 Measure 详解
  • View 绘制体系知识梳理(4) - 绘制过程之 Layout 详解
  • View 绘制体系知识梳理(5) - 绘制过程之 Draw 详解

一、getMeasuredWidth 和 getWidth 的定义

1.1 getMeasuredWidth

我们来看一下getMeasuredWidth方法的内部实现:

    /*** Like {@link #getMeasuredWidthAndState()}, but only returns the* raw width component (that is the result is masked by* {@link #MEASURED_SIZE_MASK}).** @return The raw measured width of this view.*/public final int getMeasuredWidth() {return mMeasuredWidth & MEASURED_SIZE_MASK;}
复制代码

这里可以看到,该方法返回的是setMeasuredDimensionRaw中设置的mMeasuredWidthsize部分,也就是说,该方法返回的是在 测量阶段中计算出的宽度

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));}protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {boolean optical = isLayoutModeOptical(this);if (optical != isLayoutModeOptical(mParent)) {Insets insets = getOpticalInsets();int opticalWidth  = insets.left + insets.right;int opticalHeight = insets.top  + insets.bottom;measuredWidth  += optical ? opticalWidth  : -opticalWidth;measuredHeight += optical ? opticalHeight : -opticalHeight;}setMeasuredDimensionRaw(measuredWidth, measuredHeight);}private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {mMeasuredWidth = measuredWidth;mMeasuredHeight = measuredHeight;}
复制代码

1.2 getWidth

    /*** Return the width of the your view.** @return The width of your view, in pixels.*/@ViewDebug.ExportedProperty(category = "layout")public final int getWidth() {return mRight - mLeft;}
复制代码

getWidth的值是根据mRightmLeft之间的差值计算出来的,在setFrame方法中,会对View的四个点坐标mLeft/mRigth/mTop/mBottom进行赋值,它决定了View在其父容器中所处的位置:

    protected boolean setFrame(int left, int top, int right, int bottom) {boolean changed = false;if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {changed = true;mLeft = left;mTop = top;mRight = right;mBottom = bottom;//....}return changed;}
复制代码

setFrame就是在layout过程中调用的:

    public void layout(int l, int t, int r, int b) {int oldL = mLeft;int oldT = mTop;int oldB = mBottom;int oldR = mRight;//通过之前介绍的 setFrame 方法进行赋值。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);if (shouldDrawRoundScrollbar()) {if(mRoundScrollbarRenderer == null) {mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);}} else {mRoundScrollbarRenderer = null;}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);}}}}
复制代码

1.3 小结

在之前的两篇文章 View 绘制体系知识梳理(3) - 绘制流程之 Measure 详解 和 View 绘制体系知识梳理(4) - 绘制过程之 Layout 详解,我们介绍了measurelayout的内部实现,而getMeasuredWidthgetWidth就分别对应于上面这两个阶段获得的宽度,也就是说:

  • getMeasuredWidthmeasure阶段获得的View的原始宽度。
  • getWidthlayout阶段完成后,其在父容器中所占的最终宽度

1.4 注释说明

下面是Google文档中对于上面这两个方法的注释说明:

  • getMeasuredWidth
The width of this view as measured in the most recent call to measure().
This should be used during measurement and layout calculations only.
Use getWidth() to see how wide a view is after layout.Returns: the measured width of this view
复制代码
  • getWidth
Return the width of the your view.Returns: the width of your view, in pixels
复制代码

二、示例

我们用一个简单的示例,来演示getMeasuredWidthgetWidth的区别:

2.1 布局定义

首先定义一个自定义的LinearLayout,它包含两个子View,在xml中它们的宽度都被指定为200dp

<?xml version="1.0" encoding="utf-8"?>
<com.demo.lizejun.repoopt.WidthDemoLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><Viewandroid:background="@android:color/holo_blue_bright"android:layout_width="200dp"android:layout_height="100dp"/><Viewandroid:background="@android:color/holo_orange_light"android:layout_width="200dp"android:layout_height="100dp"/>
</com.demo.lizejun.repoopt.WidthDemoLayout>
复制代码

2.2 重写 onLayout 方法

WidthDemoLayout中,我们重写它的onLayout方法,对它的子View重新摆放,并打印出getMeasuredWidthgetWidth方法的值:

public class WidthDemoLayout extends LinearLayout {public WidthDemoLayout(Context context) {super(context);}public WidthDemoLayout(Context context, @Nullable AttributeSet attrs) {super(context, attrs);}public WidthDemoLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);int childCount = getChildCount();for (int i = 0; i < childCount; i++) {View child = getChildAt(i);if (i == childCount - 1) {child.layout(child.getLeft() ,child.getTop(), child.getRight() + 400, child.getBottom());}Log.d("WidthDemoLayout", "measuredWidth=" + child.getMeasuredWidth() + ",width=" + child.getWidth());}}
}
复制代码

输出的结果为:

>> 12-04 12:48:58.788 24935-24935/com.demo.lizejun.repoopt D/WidthDemoLayout: measuredWidth=800,width=800
>> 12-04 12:48:58.788 24935-24935/com.demo.lizejun.repoopt D/WidthDemoLayout: measuredWidth=800,width=1200
复制代码

最终展示的时候,虽然我们在xml中指定了相同的宽度,但是最终显示是以getWidth为准:


更多文章,欢迎访问我的 Android 知识梳理系列:

  • Android 知识梳理目录:www.jianshu.com/p/fd82d1899…
  • Android 面试文档分享:www.jianshu.com/p/8456fe6b2…

View 绘制体系知识梳理(7) getMeasuredWidth 和 getWidth 的区别相关推荐

  1. View 绘制体系知识梳理(4) 绘制过程之 Layout 详解

    一.布局的起点 - performTraversals 和前面分析测量过程类似,整个布局的起点也是在ViewRootImpl的performTraversals当中: private void per ...

  2. View绘制体系(三)——AttributeSet与TypedArray详解

    View绘制体系(三)--AttributeSet与TypedArray详解 前言 上篇博客中讲了LayoutInflater.inflate机制,其中提到了AttributeSet和XmlPullP ...

  3. 《软件工程与实践》 |(九)软件工程新技术及体系 知识梳理

    系列索引: <软件工程与实践>第三版 软件工程课程知识梳理 目录 系列索引: <软件工程与实践>第三版 软件工程课程知识梳理 本章重难点: 9.1 软件工程新技术 9.1.1 ...

  4. getMeasuredWidth和getWidth的区别

    View的getWidth()和getMeasuredWidth()有什么区别吗? View的高宽是由View本身和Parent容器共同决定的. getMeasuredWidth()和getWidth ...

  5. View 事件传递体系知识梳理(1) 事件分发机制

    一.事件分发概述 1.1 事件分发的关键方法 对于ViewGroup来说,与事件分发相关的方法包括: public boolean dispatchTouchEvent(MotionEvent eve ...

  6. 【Android View绘制体系】invalidate

    invalidate内部思想 invalidate的调用流图 View.invalidateInternal 打上DIRTY标记 为后面Draw做准备 mPrivateFlags |= PFLAG_D ...

  7. 【Android View绘制体系】requestLayout

    如下为View的requestLayout: 经历了两步: 增加自身标记mPrivateFlags为PFLAG_FORCE_LAYOUT 调用父视图的requestLayout()方法.ViewGro ...

  8. 动画体系知识梳理(1) 转场动画 ContentTransition 理论篇

    一.概述 在Android 5.0当中,Google基于Android 4.4中的Transition框架引入了转场动画,设计转场动画的目的,在于让Activity之间或者Fragment之间的切换更 ...

  9. Loader 知识梳理(2) initLoader和restartLoader的区别

    一.概述 在前面的一篇文章中,我们分析了LoaderManager的实现,里面涉及到了很多的细节问题,我们并不需要刻意地记住每个流程,之所以需要分析,以后在使用的过程中,如果遇到问题了,再去查看相关的 ...

最新文章

  1. 如何理解numpy.nan_to_num
  2. DVWA的安装与简单使用
  3. 阿里云二面:你对限流了解多少?
  4. JavaScript 技术篇-js代码获取当前操作系统信息、浏览器版本信息实例演示,windows NT版本对照表
  5. python是什么学了有什么用处_学python有什么用途 就业方向有哪些
  6. [转]inux Kernel部分选项意义
  7. wdr和hdr的区别
  8. javascript对象包含哪些要素_让人迷糊的JavaScript对象(Object一)
  9. 如何revert一个merged branch上所有的改动
  10. .net mysql 序号_MYSQL如何自动为查询数据的结果编上序号详解
  11. HTML做出7个网页,HTML适用于除IE 7以外的每个网页浏览器。
  12. 实验楼Python项目
  13. 创维酷开电视能换成android系统吗,创维酷开电视怎么系统升级【图文教程】
  14. 8数据提供什么掩膜产品_喜茶、茶百道、书亦、古茗8月外卖热销产品数据全解析...
  15. 功能测试项目——酒店管理系统
  16. Android毕业设计选题依据,毕业设计选题依据、目的意义、
  17. 2020 — 只争朝夕,不负韶华
  18. 均质机工作原理动画_高压均质机结构图.doc
  19. 信息安全三要素(CIA):
  20. 成功路上并不拥挤 因为坚持的人不多

热门文章

  1. zabbix3.0.3-源码安装
  2. javascript:void(0)的作用示例
  3. Puppet基础篇5-如何建立master和agent之间的认证关系
  4. Three20 NetWork
  5. 如何在 Active Directory 中还原已删除的用户帐户及其组成员身份
  6. 谷歌再次修复已遭利用的两枚高危0day (CVE-2020-16009/16010)
  7. 【通告更新】Apache Tomcat服务器文件包含漏洞安全风险通告第三次更新
  8. LeetCode笔记:39. Combination Sum
  9. android与服务器交互总结(json,post,xUtils,Volley)
  10. 开源大数据周刊-第21期