android中对View的onMeasure()方法的理解
2016-01-31 15:44
579 查看
在android开发中,很多人对自定义View是望而生畏,我也一样,但这又是向高级进阶的必经之路,主要是对View里面的很多方法不知道怎么理解,其中一个就是onMeasure()方法,网上有很多这样解释说明,可能是由于我的领悟力有限,一直没能搞明白,今天有点空,好好研究一下,并记录下来,也希望对大家有所帮助。
首先,我自定义一个MyView,继承于View,onMeasure()方法不做处理,直接调用
布局文件为:
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()的实现改为:
这样一样,不管android:layout_width和android:layout_height设置的值为多少,MyView显示的宽高都为100px,一般来说我们不这样做,我们要考虑父布局给出的宽高,即我们设置android:layout_width和android:layout_height的值。
结论:
onMeasure方法的作用就是计算出自定义View的宽度和高度。这个计算的过程参照父布局给出的大小,以及自己特点算出结果
一般来说使用如下的实现过程:
大概就这样,不知道我说清楚了没有,大家有什么问题或者建议可以给我留言。
首先,我自定义一个MyView,继承于View,onMeasure()方法不做处理,直接调用
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
[code]import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.util.AttributeSet; import android.view.View; /** * Created by Administrator on 2016/1/31. */ 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); } }
布局文件为:
[code]<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()的实现改为:
[code] @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的宽度和高度。这个计算的过程参照父布局给出的大小,以及自己特点算出结果
一般来说使用如下的实现过程:
[code] @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; }
大概就这样,不知道我说清楚了没有,大家有什么问题或者建议可以给我留言。
相关文章推荐
- Android NDK开发基础——配置及简单案例
- Android流量监控类 trafficstats
- Android Studio修改默认字体大小
- Android之LayoutParams的用法
- 【完美解决】android开发 自定义字体安装包过大的问题
- Android编程技巧之自定义 Log 工具
- Android 区段加密
- Android 学习2----页面布局的学习
- Android开发学习之路--Activity之初体验
- Android开发学习之路--Activity之初体验
- Android 使用官方下拉刷新
- android-Implementing Descendant Navigation,Notifying the User
- Android的Activity切换动画特效库SwitchLayout,视图切换动画库,媲美IOS
- android学习记录3(数据存储的方式:sqlite、sp、存文件。listview简单使用)
- Android Drawable
- Android应用程序资源的编译和打包过程分析
- android *** Layout 01
- android TP(触摸屏)问题现象分析和解决方案汇总
- Fragment的设计哲学
- android armeabi与armeabi-v7a