浅析Android View的Measure过程
来源:互联网 发布:印度红色走廊 知乎 编辑:程序博客网 时间:2024/06/05 22:34
我们知道,Android的View从创建到展示给用户的过程包含了三个阶段:measure阶段、layout阶段、和draw阶段,即测量、布局、绘制。而measure则是其中之首,它测量并确定了view的宽高。当我们自定义的View的时候应该怎么样处理measure过程,重写measure过程的哪些方法呢?带着这些疑问,现简单总结下View的measure过程。
measure过程较为复杂,但核心方法只有两个:onMeasure()和measure() 方法,其中measure()方法是final的,不可重写,它调用了onMeasure()方法,在自定义View的时候我们可以重写onMeasure()方法。可以看到,这是典型的模板方法模式。
onMeasure() 方法:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));}和measure() 方法:
public final void measure(int widthMeasureSpec, int heightMeasureSpec) { boolean optical = isLayoutModeOptical(this); if (optical != isLayoutModeOptical(mParent)) { Insets insets = getOpticalInsets(); int oWidth = insets.left + insets.right; int oHeight = insets.top + insets.bottom; widthMeasureSpec = MeasureSpec.adjust(widthMeasureSpec, optical ? -oWidth : oWidth); heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight); }..... onMeasure(widthMeasureSpec, heightMeasureSpec);}
我们可以看到,measure()方法是final的,这意味着子类不能够重写这个方法,measure()是整个measure过程的核心,它测量了该view的宽高,并将宽高存放在mMeasuredwidth和mMeasuredHeight中(注:此时View中的mHeight和mWidth都未初始化,都还是0),有兴趣的朋友可以阅读源码来具体看看mMeasureWidth和mMeasuredHeight是如何初始化。此外,measure()方法内部还会调用onMeasure()方法,我们可以重写onMeasure()方法来进行其它测量操作,最常见的就是对子View进行测量。一般来说,在ViewGroup中,不仅要对自己的大小进行测量,还要依次调用各个子View的measure过程来对子View进行测量,因此我们在自定义ViewGroup时就需要重写onMeasure方法来对子类进行Measure。事实上,ViewGroup基类并没有重写onMeasure方法,只是提供了measureChildren方法来调用每个子view的measure():
ViewGroup.measureChildren()
protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) { final int size = mChildrenCount; final View[] children = mChildren; for (int i = 0; i < size; ++i) { final View child = children[i]; if ((child.mViewFlags & VISIBILITY_MASK) != GONE) { measureChild(child, widthMeasureSpec, heightMeasureSpec); } }}
measureChildren则会调用measureChild,measureChild方法则十分简单,只是获取了子view的layoutParam,调用了子view的measure方法:
protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) { final LayoutParams lp = child.getLayoutParams(); final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft + mPaddingRight, lp.width); final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, mPaddingTop + mPaddingBottom, lp.height); child.measure(childWidthMeasureSpec, childHeightMeasureSpec);}
因此,当我们在自定义布局重构measure过程时,只需要在onMeasure()方法中调用measureChildren(),就可以递归调用子类的measure过程了。
总结如下:
1、measure过程是View绘制的三大流程之首,优先于layout过程和draw过程;
2、measure过程的核心是measure()方法,measure()方法对自己的宽高进行测量,初始化mMeasuredWidth和mMeasuredHeight,并调用onMeasure方法,此时layout过程还未调用,与layout过程有关的参数都未初始化;
3、重写ViewGroup的onMeasure()方法时,在计算自己的大小同时,还要调用子View的measure,这一步骤被封装成了measureChildern(),我们可以方便地调用;
0 0
- 浅析Android View的Measure过程
- Android View measure过程
- Android应用程序窗口View的measure过程
- Android View的Measure过程(一)
- Android View的measure过程详解
- Android View ViewGroup 的measure过程
- View的measure过程
- View 的 Measure 过程
- view的measure过程
- View的measure过程
- 自定义View之Measure过程浅析
- Android View的Measure
- 018.View的Measure过程
- View的Measure过程解析
- Android中View的MeasureSpec以及Measure的过程
- 源码解析Android中View的measure量算过程
- 源码解析Android中View的measure量算过程
- 源码解析Android中View的measure量算过程
- Using "RDP Encoder Mirror Driver" to Capture Screen
- 根据进程名或者ID称关闭进程
- 第一篇博客
- linux常用命令locate,which,whereis,grep
- POJ 1270Following Orders(拓扑+DFS)
- 浅析Android View的Measure过程
- ANT教程之十三 Ant执行Java代码
- 设计模式——深入浅出单实例Singleton设计模式
- 关于任务
- JavaScript-实例(实现展开效果)
- 提升magento速度
- linux expect脚本
- 从C到OC的学习笔记一
- Putty使用教程