关键词:
在【Android】自定义 View 系列- 绘制流程 一文中,在测量过程中,是通过 一定的规则 得出最后我们测量的宽高,然后通过 setMeasuredDimension() 保存结果。
那么这里说到的规则主要就是---MeasureSpec 和 LayoutParams
MeasureSpec 是??
//源码描述
/**
* A MeasureSpec encapsulates the layout requirements passed from parent to child.
* Each MeasureSpec represents a requirement for either the width or the height.
* A MeasureSpec is comprised of a size and a mode. There are three possible modes:
* UNSPECIFIED
* The parent has not imposed any constraint on the child. It can be whatever size it wants.
* EXACTLY
* The parent has determined an exact size for the child. The child is going to be given
* those bounds regardless of how big it wants to be.
* AT_MOST
* The child can be as large as it wants up to the specified size.
*/
提取主要内容:
1.MeasureSpec 父 View 对子 View 的宽高要求。
2.MeasureSpec 包含了两个信息 模式(mode)和大小(size)
3.一共有三种模式:
UNSPECIFIED- 任意大小(It can be whatever size it wants )-例如 recyclerview 子View 的大小是超过父View 的大小的
EXACTLY - 精确值(regardless of how big is wants to be, an exact size )、
AT_MOST - 在父View 的限制范围中任意大小(as large as it wants up to the specified size).
但是,对于我们开发者来说,我们知道一个 View 的大小,不是应该由我们通过 layout_width 和 layout_height 决定的吗?
对,也不对。事实是,在对于任意一个View (包括ViewGroup),最终的大小是由父 View 的要求(MeasureSpec)和子View 自己的需求(LayoutParams-layout_width & layout_height)决定的。具体是如何决定的呢?
/**
* @param spec The requirements for this view
* @param padding The padding of this view for the current dimension and
* margins, if applicable
* @param childDimension How big the child wants to be in the current
* dimension
* @return a MeasureSpec integer for the child
*/
public static int getChildMeasureSpec(int spec, int padding, int childDimension)
int specMode = MeasureSpec.getMode(spec);
int specSize = MeasureSpec.getSize(spec);
int size = Math.max(0, specSize - padding);
int resultSize = 0;
int resultMode = 0;
switch (specMode)
// Parent has imposed an exact size on us
case MeasureSpec.EXACTLY:
if (childDimension >= 0)
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
else if (childDimension == LayoutParams.MATCH_PARENT)
// Child wants to be our size. So be it.
resultSize = size;
resultMode = MeasureSpec.EXACTLY;
else if (childDimension == LayoutParams.WRAP_CONTENT)
// Child wants to determine its own size. It can't be
// bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
break;
// Parent has imposed a maximum size on us
case MeasureSpec.AT_MOST:
if (childDimension >= 0)
// Child wants a specific size... so be it
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
else if (childDimension == LayoutParams.MATCH_PARENT)
// Child wants to be our size, but our size is not fixed.
// Constrain child to not be bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
else if (childDimension == LayoutParams.WRAP_CONTENT)
// Child wants to determine its own size. It can't be
// bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
break;
// Parent asked to see how big we want to be
case MeasureSpec.UNSPECIFIED:
if (childDimension >= 0)
// Child wants a specific size... let them have it
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
else if (childDimension == LayoutParams.MATCH_PARENT)
// Child wants to be our size... find out how big it should
// be
resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
resultMode = MeasureSpec.UNSPECIFIED;
else if (childDimension == LayoutParams.WRAP_CONTENT)
// Child wants to determine its own size.... find out how
// big it should be
resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
resultMode = MeasureSpec.UNSPECIFIED;
break;
//noinspection ResourceType
return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
(上面代码逻辑很简单,源码的注解也很贴心了,请各位耐心读完。然后再看下面的总结表格,切忌死记硬背下面的表格)
总结为表格,其中:childDimension(子View 自身大小)、size(父view剩余空间)
EXACTLY | AT_MOST | UNSPECIFIED | |
具体值 (即 childDimension ≥ 0) | 模式:EXACTLY 大小:childDimension | 模式:EXACTLY 大小:childDimension | 模式:EXACTLY 大小:childDimension |
match_parent | 模式:EXACTLY 大小:size | 模式:AT_MOST 大小:size | 模式:UNSPECIFIED 大小:View.sUseZeroUnspecifiedMeasureSpec ? 0 : size |
wrap_content | 模式:AT_MOST 大小:size | 模式:AT_MOST 大小:size | 模式:UNSPECIFIED 大小:View.sUseZeroUnspecifiedMeasureSpec ? 0 : size |
今日疑问:为什么在一次事件序列中 onInterceptTouchEvent() 返回 true 后就不会再次执行onInterceptTouchEvent() 了,而在下一次事件序列中又会再次触发吗?
这个问题,我暂时没有找到切确的答案。截止目前研究,暂时认为是 mGroupFlags 标志被改变后,导致进入 onInterceptTouchEvent() 不再触发,并且在 UP/CANCEL/HOVER_MOVE 和下次事件序列开始(即 DOWN) 会调用 resetTouchState() 重置状态。这样又可以触onInterceptTouchEvent()。
对于 MeasureSpec 的内容和 上述疑问欢迎大家评论区交流~
攻克android软键盘的疑难杂症
系列教程:推翻自己和过往,重学自定义View自定义View系列教程01–常用工具介绍自定义View系列教程02–onMeasure源码详尽分析自定义View系列教程03–onLayout源码详尽分析自定义View系列教程04–Draw源码分析及其实践自定义View系列教... 查看详情
android自定义view详解(代码片段)
View的绘制系列文章:AndroidView绘制流程之DecorView与ViewRootImplAndroidView的绘制流程之Measure过程详解(一)AndroidView的绘制流程之Layout和Draw过程详解(二)AndroidView的事件分发原理解析对于Android开发者来说,原生控件往往无法满足要求,... 查看详情
android自定义的dialog怎么设置view
自定义的dialog例子很多,通过measure方法进行绘制参考技术AViewview=LayoutInflater.from(this).inflate(resource,null);dialog.setView(view); 查看详情
android自定义view系列实战篇-view(代码片段)
QRatingViewAcustomviewforratingwhicheasytomakeanduse,butfunctionisexcellent.github-QRatingViewEffectPictureProperties<declare-styleablename="QRatingView"><!--未选中图片--><attrna 查看详情
android自定义view系列-measurespec(代码片段)
在【Android】自定义View系列-绘制流程一文中,在测量过程中,是通过一定的规则得出最后我们测量的宽高,然后通过setMeasuredDimension()保存结果。那么这里说到的规则主要就是---MeasureSpec和LayoutParamsMeasureSpec是?ÿ... 查看详情
自定义view系列一自定义view的构造函数,自定义属性(代码片段)
...列一自定义View的构造函数,自定义属性引:自定义View对于Android开发者是一道坎.虽然说是坎但是也得走过去的!此系列文章作为学习自定义View的一系列学习笔记.在进入学习自定义View的殿堂, 查看详情
128view绘制流程&自定义view
记清楚函数调用的顺序才能准确地进行调用。根据调用链,可将整个绘制过程分为三部分:Measure-Layout-DrawMeasure过程1.测量过程由上至下,在measure过程的最后,每个视图将存储自己的尺寸大小和测量规格。2.measure过程会为一个View... 查看详情
自定义view基础-最易懂的自定义view原理系列
前言自定义View原理是Android开发者必须了解的基础;在了解自定义View之前,你需要有一定的知识储备;本文将全面解析关于自定义View中的所有知识基础。目录1.View的分类视图View主要分为两类:类别解释特点单一视图即一个View,... 查看详情
android自定义view系列-measurespec(代码片段)
在【Android】自定义View系列-绘制流程一文中,在测量过程中,是通过一定的规则得出最后我们测量的宽高,然后通过setMeasuredDimension()保存结果。那么这里说到的规则主要就是---MeasureSpec和LayoutParamsMeasureSpec是?ÿ... 查看详情
android自定义view系列-measurespec(代码片段)
在【Android】自定义View系列-绘制流程一文中,在测量过程中,是通过一定的规则得出最后我们测量的宽高,然后通过setMeasuredDimension()保存结果。那么这里说到的规则主要就是---MeasureSpec和LayoutParamsMeasureSpec是?ÿ... 查看详情
android自定义view系列实战篇-viewgroup(代码片段)
...详尽地写在代码中。先上效果图兄弟们,上代码importandroid.content.Cont 查看详情
android自定义view系列-view(代码片段)
QRatingViewAcustomviewforratingwhicheasytomakeanduse,butfunctionisexcellent.github-QRatingViewEffectPictureProperties<declare-styleablename="QRatingView"><!--未选中图片--><attrname="normalIcon"format="reference"/><!--选中图片--><... 查看详情
android自定义view系列实战篇-view(代码片段)
QRatingViewAcustomviewforratingwhicheasytomakeanduse,butfunctionisexcellent.github-QRatingViewEffectPictureProperties<declare-styleablename="QRatingView"><!--未选中图片--><attrname="normalIcon"format="reference"/><!--选中图片--><... 查看详情
android进阶知识——view的工作原理(代码片段)
文章目录1.初识ViewRoot和DecorView2.理解MeasureSpec2.1MeasureSpec2.2MeasureSpec和LayoutParams的对应关系4.View的工作流程3.1measure过程3.2layout过程3.3draw过程4.自定义View4.1自定义View的分类4.2自定义View须知4.3自定义View示例本章我们主要介绍两个方... 查看详情
android自定义view之自定义一个简单的阶梯式布局(代码片段)
onMeasure:确定自身的大小确定子View的大小流程:1.ViewGroup开始测量自己的尺寸2.为每个子View计算测量的限制信息3.把上一步确定的限制信息,传递给每一个字View,然后子View开始measure自己的尺寸4.获取子View测量完... 查看详情
android群英传笔记系列三view的自定义:实现一个模拟下载
1.实现效果:动态显示进度(分别显示了整个的动态改变的过程,然后完成后,弹出一个对话框) 2.实现过程:可以分为绘制一个圆,圆弧和文本三部分,然后在MainAcitivity中通过线程模拟下载进度。a.定义... 查看详情
android自定义view系列-viewgroup(代码片段)
...尽地写在代码中。先上效果图 兄弟们,上代码importandroid.content.Contextimportandroid.graphics.Rectimportandroid.util.AttributeSetimportandroid.view.ViewGroupimportandroidx.core.view.childrenimportkotlin.math.max/****@Author:QCoder*@CreateDate:2021/12/6*@Descrip... 查看详情
讲讲android为自定义view提供的surfaceview(代码片段)
系列文章目录讲讲Android为自定义view提供的SurfaceView文章目录系列文章目录前言一、Android为什么会提供SurfaceView二、先看看AndroidDemo的实现1.实现接口以及接口定义的方法2.与Activity生命周期进行绑定3.完成初始化操作4.实现5.运行三... 查看详情