Android学习—简单自定义View(一)

最近手上不忙所以回顾了一下自己今年来所接触和学习的东西,突然觉得写博客真是一个很好的方式,希望自己 可以坚持下去。

自定义View的流程

  • 创建自定义类继承View,并重写构造方法,构造方法总共有四种,我们暂时只需要继承前两种
public CircleView(Context context) {
    super(context);
}

public CircleView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
}

第一种构造方法是在你动态添加自定义View的时候使用
Android学习—简单自定义View(一)
第二种构造方法是在xml中使用时调用

<example.com.testactivity.CircleView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"/>
  • 重写onDraw()方法
/**
 * 重写绘制的方法
 * @param canvas
 */
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawColor(Color.parseColor("#018172")); // 1.设置背景色
    float radius=100;                 //半径
    float x=100;
    float y=100;
    Paint paint=new Paint();            //实例化一个paint对象      画笔
    paint.setColor(Color.WHITE);                    // 2.设置画笔颜色
    paint.setStyle(Paint.Style.STROKE);         //空心,默认是实心
    canvas.drawCircle(x,y,radius,paint);        //指定绘制的形状 画圆

}

paint.setStyle(Paint.Style.STROKE)设置画笔的风格,可以指定圆心是实心还是空心,该方法主要用于矩形和圆型

  • Style.FILL:实心

  • Style.FILL_AND_STROKE:同时显示实心和空心

  • Style.STROKE:空心

  • 重写onMeasure方法

/**
 - 作用:如果想在xml中实现自适应大小 就需要重写该方法 给这个View一个原始大小值
 - @param widthMeasureSpec
 - @param heightMeasureSpec
 */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width=200;
    int height=200;            //设置View自适应的原始大小

    int HEIGHT_MODE=MeasureSpec.getMode(heightMeasureSpec);        // 1.根据提供的测量值(格式)提取模式(下述三个模式之一)    
    int HEIGHT_SIZE=MeasureSpec.getSize(heightMeasureSpec);         //2.根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)    
    int WIDTH_MODE=MeasureSpec.getMode(widthMeasureSpec);
    int WIDTH_SIZE=MeasureSpec.getSize(widthMeasureSpec);               

    if (HEIGHT_MODE==MeasureSpec.EXACTLY){                             //如果测量模式是精确模式 那么直接使用获取的值
        height=HEIGHT_SIZE;
    }else if (HEIGHT_MODE==MeasureSpec.AT_MOST){
        height=Math.min(height,HEIGHT_SIZE);                       //如果xml中设置的是wrap_content 即是该模式,取最小值
    }
    if (WIDTH_MODE==MeasureSpec.EXACTLY){
        width=WIDTH_SIZE;
    }else if (WIDTH_MODE==MeasureSpec.AT_MOST){
        width=Math.min(width,WIDTH_SIZE);
    }
    setMeasuredDimension(width,height);                   //测量完毕后 使用该方法设置真正的大小
}

注意:MeasureSpec.getMode(heightMeasureSpec) 表示获取在xml中设置的高的模式
总共有三种模式

  • EXACTLY 精确模式 当设置的长度为match_parent或者给定一个具体大小时
  • AT_MOST 当设置为wrap_content时
  • UNSPECIFIED 该模式很少用到

参考链接