view的onMeasure,onLayout,onDraw源码分析(下)
来源:互联网 发布:中国真实gdp季度数据 编辑:程序博客网 时间:2024/06/07 00:24
1, 引子
一直以为绘制的三个方法onMeasure,onLayout,和onDraw只调用一次,分析源码时也没有在意,后来在看listview时发现onLayout居然调用了2次,然后就有些疑惑了,这些方法到底是调用几次。其实, ViewRootImpl 的performTraversals方法调用2次, View的onMeasure方法至少调用2次, onLayout方法调用2次, onDraw方法调用1次。调用顺序如下,
performTraversals –>onMeasure-->onMeasure-->onLayout
performTraversals –>onMeasure--> onLayout -->onDraw
2, 2次performTraversals
ViewRootImpl 的performTraversals部分源码如下,
private void performTraversals() { mIsInTraversal = true; mWillDrawSoon = true; boolean windowSizeMayChange = false; boolean newSurface = false; boolean surfaceChanged = false; WindowManager.LayoutParams lp = mWindowAttributes; ~~~if (!cancelDraw && !newSurface) { if (!skipDraw || mReportNextDraw) { if (mPendingTransitions != null && mPendingTransitions.size() > 0) { for (int i = 0; i < mPendingTransitions.size(); ++i) { mPendingTransitions.get(i).startChangingAnimations(); } mPendingTransitions.clear(); } performDraw(); } } else { if (viewVisibility == View.VISIBLE) { // Try again scheduleTraversals(); } else if (mPendingTransitions != null && mPendingTransitions.size() > 0) { for (int i = 0; i < mPendingTransitions.size(); ++i) { mPendingTransitions.get(i).endChangingAnimations(); } mPendingTransitions.clear(); } } mIsInTraversal = false; }
第1次执行performTraversals方法时, newSurface为false,所以会执行scheduleTraversals方法,该方法最后又会调用performTraversals方法,第2次执行performTraversals方法时,newSurface为true,所以会调用performDraw方法,最后会调用onDraw方法。
3, measure
View的measure部分源码如下,
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {~~~if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT || widthMeasureSpec != mOldWidthMeasureSpec || heightMeasureSpec != mOldHeightMeasureSpec) { ~~~ if (cacheIndex < 0 || sIgnoreMeasureCache) { // measure ourselves, this should set the measured dimension flag back onMeasure(widthMeasureSpec, heightMeasureSpec); mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; } ~~~}
有些ViewGroup可能会让自己的子视图测量两次。比如说,父视图先让每个子视图自己测量,使用View.MeasureSpec.UNSPECIFIED,然后在根据每个子视图希望得到的大小不超过父视图的一些限制,就让子视图得到自己希望的大小,否则就用其他尺寸来重新测量子视图。这一类的视图有FrameLayout,RelativeLayout等。所以,在measure方法中,对重新调用onMeasure方法有些限制。
所以, measure方法至少会调用2次, onLayout一定会调用2次, onDraw方法仅会调用1次。
4,View状态
View状态的种类非常多,一共有十几种类型,不过多数情况下我们只会使用到其中的几种,因此这里我们也就只去分析最常用的几种视图状态。
enabled
setEnabled
isEnabled
focused
setFocusable
isFocusable
selected
pressed
enabled
setEnable()方法来改变视图的可用状态,传入true表示可用,传入false表示不可用。它们之间最大的区别在于,不可用的视图是无法响应onTouch事件的。
focused
表示当前视图是否获得到焦点。通常情况下有两种方法可以让视图获得焦点,即通过键盘的上下左右键切换视图,以及调用requestFocus()方法。
selected
表示当前视图是否处于选中状态。一个界面当中可以有多个视图处于选中状态,调用setSelected()方法能够改变视图的选中状态,传入true表示选中,传入false表示未选中。
pressed
表示当前视图是否处于按下状态。可以调用setPressed()方法来对这一状态进行改变,传入true表示按下,传入false表示未按下。
一般当View的状态发生改变时,会重新绘制View,刷新界面。
当View的状态发生改变时,最后都会调用ViewRootImpl的performTraversals方法进行刷新,具体的细节就不多说了。
- view的onMeasure,onLayout,onDraw源码分析
- view的onMeasure,onLayout,onDraw源码分析(下)
- view的onlayout,onmeasure,ondraw
- 源码分析:onAttach, onMeasure, onLayout, onDraw 的顺序。
- [置顶] 源码分析:onAttach, onMeasure, onLayout, onDraw 的顺序。
- 源码分析:onAttach, onMeasure, onLayout, onDraw 的顺序。
- 关于View的onMeasure()、onSizeChanged()、onLayout()、onDraw()调用顺序
- 关于View的onMeasure()、onSizeChanged()、onLayout()、onDraw()调用顺序
- 自定义View(三) 之 onMeasure() onLayout() onDraw()
- 自定义View之onMeasure(),onLayout(),onDraw()
- 自定义View中的onMeasure,onLayout,onDraw
- 自定义View中的onMeasure,onLayout,onDraw
- 自定义view之onMeasure,onLayout,onDraw
- 一个关于View/ViewGroup onMeasure() onLayout()被调用了但是onDraw()没有被调用的问题分析
- Android onMeasure,onLayout,onDraw的理解
- onMeasure(),onLayout(),onDraw
- onMeasure,onLayout,onDraw
- onMeasure onLayout onDraw
- Hyper-v 2016 VHD Se
- JavaScript中的apply()方法和call()方法
- Java web网站访问量的计数
- 关于项目统一管理android.index.js和ios.index.js
- UML的宏观理解
- view的onMeasure,onLayout,onDraw源码分析(下)
- Word 通过添加Package 实现word藏毒
- Spring Boot系列教程十二:Spring boot集成Redis
- 2016人生总结
- Java从头复习:java概述
- HDU 5745 dp, bitset优化
- 正则表达式语法速查表
- UOJ164 V 线段树lazytag维护历史最值
- 微信OAuth2.0网页授权snsapi_userinfo方式java版