在Android开发中,很多人对自定义View是望而生畏,但这又是向高级进阶的必经之路,主要是对View里面的很多方法不知道怎么理解,其中一个就是onMeasure()方法。

首先,我自定义一个MyView,继承于View,onMeasure()方法不做处理,直接调用super.onMeasure(widthMeasureSpec, heightMeasureSpec);

public class MyView extends View{
public MyView(Context context) {
super(context);
} public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
} public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
} @TargetApi(Build.VERSION_CODES.LOLLIPOP)
public MyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}

布局文件为:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <com.example.customviewdemo.View.MyView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:padding="10dp"
android:background="#ff0000"/> </LinearLayout>

onMeasure()方法的作用就是测量View需要多大的空间,就是宽和高,在MyView中我没有做任何处理,使用View默认的测量规则,我们看下效果:

在android:layout_width和android:layout_height都为match_parent的时候,MyView填满全屏,当我们把android:layout_width和android:layout_height都为wrap_content的时候,我们看到MyView还是填满全屏,当我把android:layout_width和android:layout_height都这是为100dp的时候,我们看下效果

我们看到MyView的大小为100dp了。

结论:

1、View默认的测量规则是android:layout_width和android:layout_height为match_parent或者wrap_content时,是填充全屏的。

2、android:layout_width和android:layout_height设置为具体值时,那么是多少,宽高就是多少。

显然,默认的规则大部分不符合我们的需求,先来看下onMeasure()的参数,有两个参数,widthMeasureSpec,heightMeasureSpec,以前不明白,我以为是View本身的大小,仔细想想也不对,如果是本身的大小那还要你测什么啊,这两个参数是父布局给它提供的水平和垂直的空间要求,大家注意,只是父布局提供的要求,当然View也可以不遵守在View的android:layout_width和android:layout_height的值就是onMeasure()两个参数。什么意思,比如我为android:layout_width和android:layout_height设置的值为300dp,但是我在onMeasure()中,测量时不遵守这个300dp的空间要求,将onMeasure()的实现改为:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(100,100);
}

这样一样,不管android:layout_width和android:layout_height设置的值为多少,MyView显示的宽高都为100px,一般来说我们不这样做,我们要考虑父布局给出的宽高,即我们设置android:layout_width和android:layout_height的值。
结论:
onMeasure方法的作用就是计算出自定义View的宽度和高度。这个计算的过程参照父布局给出的大小,以及自己特点算出结果
一般来说使用如下的实现过程: 

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
} private int measureWidth(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
//设置一个默认值,就是这个View的默认宽度为500,这个看我们自定义View的要求
int result = 500;
if (specMode == MeasureSpec.AT_MOST) {//相当于我们设置为wrap_content
result = specSize;
} else if (specMode == MeasureSpec.EXACTLY) {//相当于我们设置为match_parent或者为一个具体的值
result = specSize;
}
return result;
} private int measureHeight(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
int result = 500;
if (specMode == MeasureSpec.AT_MOST) {
result = specSize;
} else if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
}
return result;
}

  

  

  

最新文章

  1. javaEE-----org.springframework.dao.InvalidDataAccessApiUsageException: Write operation
  2. BZOJ 1564: [NOI2009]二叉查找树
  3. composer快速入门
  4. db2 表授权语句
  5. 解决本地tomcat服务器内存不足问题
  6. poi 读取 excel(.xlsx) 2007及以上版本
  7. 编译安装-Apache
  8. [AngularJS] Using ngModel in Custom Directives
  9. HDU 5965 扫雷 【模拟】 (2016年中国大学生程序设计竞赛(合肥))
  10. KMP算法总结
  11. JavaScript arguments类数组
  12. BlazeDS简介(转自openkk的日志)
  13. perl 安装 ZooKeeper模块
  14. [PHP]Symfony or Laravel 在 console 中结合 Workerman
  15. 利用Lua读写本地文件
  16. Matlab绘图基础——图形绘制的插值
  17. AQS源码阅读笔记(一)
  18. volume.go
  19. 同步手绘板——android端取色
  20. pyppeteer使用笔记

热门文章

  1. 【数据库】:关于DB2数据库错误提示说明
  2. .NET 知识点总结
  3. js继承的实现(es5)
  4. golang-开发配置
  5. master线程的主循环,后台循环,刷新循环,暂停循环
  6. Spring源码深度解析系列-----------org.springframework.aop-3.0.6.RELEASE
  7. 【LeetCode题解】350_两个数组的交集Ⅱ
  8. An Introduction to Computer Thinking
  9. Ruby(1):入门
  10. LOJ #6022. 重组病毒