OnMeasure方法详解
来源:互联网 发布:北京电视台网络直播 编辑:程序博客网 时间:2024/06/11 03:17
在自定义view中,我们会遇到最重要的三个方法。OnMeasure,OnLayout OnDraw。OnLayout决定了在ViewGroup中的位置。 OnDraw决定了如何绘制这个view。而在这里要介绍的OnMeasure决定了View的大小。
先来看下TextView中的OnMeasure方法:
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
- int width;
- int height;
- ...
- if (widthMode == MeasureSpec.EXACTLY) {
- // Parent has told us how big to be. So be it.
- width = widthSize;
- } else {
- if (mLayout != null && mEllipsize == null) {
- des = desired(mLayout);
- }
- ...
- setMeasuredDimension(width, height);
首先要先明白是谁调用了onMeasure()这个方法。 调用它的是这个view的父视图。widthMeasureSpec和heightMeasureSpec这两个参数由其父视图viewGroup的layout_height,layout_width,padding以及本身的layout_margin,layout_width,layout_height共同决定(其实还与widght权重有关,但是这个比较复杂先忽略它)。
接着要来说一下widthMeasureSpec的组成结构,它包含了两部分,Mode and Size. 你可以会奇怪为啥一个Int能包含两部分信息。 其实它是一个32位的,高两位用于表示Model,低30位表示Size。 Model由本身view和Viewgroup的layout_width有关,Size与ViewGroup中得Padding,本身的margin,layout_width。
先来说说Model,它有三种状态:
exactly精确状态01:MeasureSpec.EXACTLY:view就为本身指定的大小,再xml中定义的为MATCH_PARENT时model对应于EXACTLY
at_most最大状态00:MeasureSpec.AT_MOST:view的大小不得大于VIewGroup的大小,再xml中定义的为WRAP_CONTENT对应为于AT_MOST
unspecified为指明状态10:MeasureSpec.UNSPECIFIED: view的大小不受限制,当view设置为制定大小时情况对应这种
32位的数字解析出来稍微有点麻烦,所以Google官方也提供了几个方法来获取Model 和Size——MeasureSpec.getModel和MeasureSpec.getSize。 如下的代码是一个列子,注意了setMeasuredDimension(width,height)这里的高宽才是最后真真的大小。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); Log.e("Measure",MeasureSpec.toString(widthMeasureSpec)); int width; int height; if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; } else { mPaint.setTextSize(mTitleTextSize); mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); float textWidth = mBound.width(); int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight()); width = desired; } if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; } else { mPaint.setTextSize(mTitleTextSize); mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); float textHeight = mBound.height(); int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom()); height = desired; } setMeasuredDimension(width, height);}
在这里顺便提一下一种让listview或者gridview取消滚动栏方法的实现原理
int expandSpec= MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE,MEASURESPEC.AT_MOST);
super.onMeasure(widthMeasureSpec,expandSpec)
makeMeasureSpec这个方法是传入size和model返回一个MeasureSpec值。还记得前面说的吗,高两位是model,低位是size,这里我们把最大的整形左移两位空出model的值,剩下的size部分就是30位的最大值了,即size为最大;然后我们又让model设置为AT_MOST即wrap_content有多大显示多大,这样view的高度就成了view本身有多大就显示多大,就不会出现自带的滚动条了~
0 0
- OnMeasure方法详解
- Android中onMeasure方法详解
- 继承ViewGroup重写onMeasure方法的详解
- Android 自定义控件onMeasure()方法详解
- 继承ViewGroup重写onMeasure方法的详解
- Android View中的onMeasure()方法详解
- onMeasure(),onLayout(),onDraw(),invalidate()方法详解
- 自定义控件的onMeasure方法详解
- 自定义View控件之onMeasure方法详解
- onMeasure方法
- onMeasure方法
- 详解onMeasure()方法中如何测量一个控件尺寸
- 自定义view当中的onmeasure()方法详解
- 自定义View(三)之View类的onMeasure方法详解
- onMeasure流程,MeasureSpec详解
- View onMeasure 测量方法详解
- Android View onMeasure 方法
- View的onMeasure方法
- Fastjson 自定义输出
- Reachability网络情况之详解
- pg_multixact manager for shared-row-lock implementation
- 黑马程序员——继承
- Jackson
- OnMeasure方法详解
- 添加Aop声明式事务处理java.lang.NoSuchMethodError: org.springframework.util.ClassUtils.isUserLevelMethod
- [转]MySQL 调优/优化的 100 个建议
- 高斯(核)函数简介
- 黑马程序员——面向对象
- Android handler机制的原理
- OC基础-拷贝
- Tomcat Gzip配置
- lintcode-快速幂-125