Android自定义View的基础知识(二)——onMeasure方法的介绍

在编写自定义view时,除了onDraw方法很重要,可以绘制自定义view当中的内容,onMeasure方法也很重要,主要负责测量自定义view显示的宽高,然后对于布局的设置进行获取,并且根据具体情况改变宽高。

     关于onMeasure方法具体的作用,和其中包括知识点我们通过一个例子来介绍,我们希望能够无论在布局当中如何设置自定义控件的宽高,都能够显示出完整的圆,并且可以在布局改变圆的颜色。

     上述需求实现的分析:

1.既然不管在布局文件当中如何设置宽度和高度,都要出现圆,圆有外切正方形,所以必须先确定正方形。

      2.在onMeasure方法当中对于设置的宽度和高度进行获取,然后比较小的边,就作为圆的直径,正方形的边长。

      3.因为要求在布局当中能够随意改变圆的颜色,所以需要写一个自定义属性。

既然分析出了,需要改变的属性,就可以写自定义属性在res/values/attrs.xml文件当中,如果有直接在attrs文件夹当中开启新的declared-styable标签,如果没有就创建attrs文件,并写出新的标签。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--declare-styleable标签适用于放置自定义属性的标签,name对应的值便是在自定义view当中查找的对应的属性-->
    <declare-styleable name="CustomView">
        <attr name="circleColor" format="color"/>
    </declare-styleable>
</resources>

然后就去创建一个类,继承view,编写构造方法,重写onDraw方法和onMeasure方法了

public class CustomView extends View{
    public int size = 200;
    Paint paint ;
//    用于在布局当中进行使用的
    public CustomView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        paint.setStyle(Paint.Style.FILL);//设置画笔是实心的
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
        int color = typedArray.getColor(R.styleable.CustomView_circleColor, Color.YELLOW);
        paint.setColor(color);  //设置画笔的颜色
        typedArray.recycle();//回收资源
    }
//  绘制界面的方法
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/2,paint);
    }
//  onMeasure   :负责测量控件的宽度和高度的方法
/**
 * widthMeasureSpec: 父容器允许的该控件的最大宽度
 * heightMeasureSpec: 父容器允许的该控件的最大高度
 * 实际作用其实就是在布局当中对于宽高的设置。
 * MeasureSpec :是view的内部类,反映了view宽度和高度的测量。
 * 传入的参数当中包含了两个信息widthMeasureSpec,分别是测量的模式和最大的尺寸
 * 测量的模式一个分为3种
 * 1.MeasureSpec.AT_MOST:代表不固定的数值,根据内部的内容进行展示,通常定义wrap_content作为传入的数值
 * 2.MeasureSpec.EXACTLY :代表精确的数值,当view的宽度和高度被定义为match_parent或者精确值时就是这种模式。
 * 3.MeasureSpec.UNSPECIFIED :没有限制的,不固定的。
 * 要求:不管在布局当中设置的宽高是多少,我要求显示的就是正方形。
 * 分析找到宽高比较小的哪个边,以哪个边的长度作为正方型的边长
 * */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//        在布局里面设置宽度的测量模式
        int wMode = MeasureSpec.getMode(widthMeasureSpec);
//        在布局当中设置的高度的测量模式
        int hMode = MeasureSpec.getMode(heightMeasureSpec);
//        获取宽度和高度固定的尺寸
        int wsize = MeasureSpec.getSize(widthMeasureSpec);
        int hsize = MeasureSpec.getSize(heightMeasureSpec);
//        对于在xml布局当中的宽度的设置进行判断,判断是精确值还是wrap_content
        switch (wMode) {
            case MeasureSpec.AT_MOST:   //在布局当中设置宽度是wrap_content
                if (hMode== MeasureSpec.AT_MOST) {
                    wsize = hsize = size;
                }else if (hMode== MeasureSpec.EXACTLY) {
                    int minSize = Math.min(size, hsize);
                    wsize = hsize = minSize;
                }
                break;
            case MeasureSpec.EXACTLY:   //在布局当中设置宽度为match_parent或者是精确值
                if (hMode== MeasureSpec.AT_MOST) {
                    int minSize = Math.min(wsize, size);
                    wsize = hsize = minSize;
                }else{
                    int min = Math.min(hsize, wsize);
                    wsize=hsize=min;
                }
                break;
        }
//      调用设置宽度和高度的方法,对于该控件在布局的尺寸进行设置
        setMeasuredDimension(wsize,hsize);
    }
}


ok~然后就可以在布局当中引入这个控件了!

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.animee.day405.demo02.CustomView
        android:id="@+id/custom_view"
        android:layout_width="200dp"
        android:layout_height="match_parent"
        app:circleColor="#00FF00"/>
</LinearLayout>

然后大家就会发现,无论高度和宽度如何设置,都会保持形成正方形,然后通过正方形产生了内切圆。然后通过app引用自定义属性circleColor就可以随意的改变圆的颜色了。就如下图所示!





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值