Android自定义view初识(一)

爱哥的自定义View其实很简单
鸿洋大神的Android自定义view
Android群英传(徐宜生)

自定义View这件事,确实如鸿洋大神所说,对于新手来说是一件比较恐怖的事情。比如在下这只小菜鸟,一直想好好学习自定义View,却又总是半途而废。这一次,一定坚持掌握自定义View技巧。

那么让我们进入正题:
在学习自定义View之前,先让我们了解一下Android的控件架构

在Android中,控件大致被分为两类:VIew和ViewGroup。
ViewGroup作为父控件,可以包含多个View,并对其进行管理。通过ViewGroup,整个界面上就形成了一个控件树,上层控件负责对下层控件的测量和绘制。并且传递交互事件。通常,我们用到的findviewById就是通过遍历控件树来寻找对应的元素。

Android自定义view初识(一)_第1张图片
view树结构
Android自定义view初识(一)_第2张图片
UI界面架构图

好的,简单的了解一下,让我们进入正题,究竟如何实现自定义view呢。
在Android中,自定义View必定是继承View或者是VIew的子控件,如:Button、TextView等等。

首先我们继承自VIew。

public class MyCircle extends View {
}

IDE主动提示我们要声明构造方法;


 public CustomCircle(Context context) {
            this(context, null);
      }
//此构造方法解析Android自带的属性
      public CustomCircle(Context context, AttributeSet attrs) {
            this(context, attrs, 0);

      }
//此构造方法解析自定义的属性
      public CustomCircle(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);    
      }

我们重写了三个构造方法,将前两个方法中的super该为this,如果不改的话,会在onDraw中使用画笔的时候报空指针异常,因为根本走不到第三个构造方法。

接下来我们先重写onDraw方法,

 @Override
      protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
      }

当我们要画一些什么的时候,我们就要在这个方法中进行操作,在现实生活中,我们如果想要画画的话,首先需要的就是画笔和画板。当然,Android也给我们提供了Paint和Canvas,一个是画笔,当然另一个就是画布啦。我们可以看到,在onDraw方法中,画布Canvas是作为参数传递进了这个方法中,也就是说这个画布是Android为我们准备好的,我们不用去管就是了。

好了,现在有了画布,我们还需要一个画笔Paint,
在爱哥的博客中我们知道,因为Android不建议我们在draw和layout的过程中去初始化话画笔,因为这两个过程可能是需要频繁进行重复操作的过程,我们知道new是需要分配内存空间的,如果我们如此频繁的去进行new操作,内存会不会爆呢?这个我们并不知道,但浪费内存这个确实可以肯定的。所以Android不建议我们在这两个过程中初始化画笔。
那我们就在构造方法中实例化对象

  public CustomCircle(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mContext = context;
            initPaint();

      }

      private void initPaint() {

            //初始化画笔并打开抗锯齿模式
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            /*
         * 设置画笔样式为描边并填充
         *
         * 画笔样式分三种:
         * 1.Paint.Style.STROKE:描边(圆环嘛)
         * 2.Paint.Style.FILL_AND_STROKE:描边并填充
         * 3.Paint.Style.FILL:填充
         */
            mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            // 设置画笔颜色为黄色
            mPaint.setColor(Color.YELLOW);
            /*
         * 设置描边的粗细,单位:像素px
         * 注意:当setStrokeWidth(0)的时候描边宽度并不为0而是只占一个像素
         */
          //  mPaint.setStrokeWidth(10);
      }

现实中的画笔,我们可以去挑选颜色、类型等等等等各种属性,当然在Android我们也可以去设置paint的各种属性,现实中有的,Android有,现实中没有的,Android还有。


Android自定义view初识(一)_第3张图片
Paint.set

当然,Paint集成了画的属性,那么Canvas就定义了我们所要画的东西。

Android自定义view初识(一)_第4张图片
Canvas.draw
@Overrideprotected void onDraw(Canvas canvas) {      super.onDraw(canvas);    
/*
* 画一个圆,
* 第一个参数为水平方向的中心坐标
* 第二个参数为垂直方向的中心坐标
* 第三个参数为圆的半径
* 第四个参数为我们的画笔
* */
  canvas.drawCircle(MeasureUtil.getScreenSize((Activity) mContext)[0] / 2, 300, radiu, mPaint);      }

现在我们的圆是确确实实的画出来了

Android自定义view初识(一)_第5张图片

按照爱哥的想法,我们现在要实现让圆从小到大不断的变化。
就这样我们让我们的class实现了Runnable方法,

 @Override
      public void run() {
             /*
     * 确保线程不断执行不断刷新界面
     */
            while (true) {
                  try {
            /*
             * 如果半径小于200则自加否则大于200后重置半径值以实现往复
             */
                        if (radiu <= 200) {
                              radiu += 10;

                              // 刷新View
                              postInvalidate();
                        } else {
                              radiu = 0;
                        }

                        // 每执行一次暂停40毫秒
                        Thread.sleep(40);
                  } catch (InterruptedException e) {
                        e.printStackTrace();
                  }
            }
      }

在activity中启动线程:

new Thread(mCustomView).start();

完整代码

package com.bx.myproject.MyView;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

import com.bx.myproject.R;

public class CustomCircle extends View implements Runnable{

      private Context mContext;//上下文引用
      private Paint mPaint;  //画笔
      private String mText;
      private int mTextColor;
      private int mTextSize;

      private int radiu;// 圆环半径

      public CustomCircle(Context context) {
            this(context, null);
      }

      public CustomCircle(Context context, AttributeSet attrs) {
            this(context, attrs, 0);

      }

      public CustomCircle(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mContext = context;
            initPaint();

      }

      private void initPaint() {

            //初始化画笔并打开抗锯齿模式
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            /*
         * 设置画笔样式为描边,圆环嘛……当然不能填充不然就么意思了
         *
         * 画笔样式分三种:
         * 1.Paint.Style.STROKE:描边
         * 2.Paint.Style.FILL_AND_STROKE:描边并填充
         * 3.Paint.Style.FILL:填充
         */
            mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            // 设置画笔颜色为浅灰色
            mPaint.setColor(Color.YELLOW);
            /*
         * 设置描边的粗细,单位:像素px
         * 注意:当setStrokeWidth(0)的时候描边宽度并不为0而是只占一个像素
         */
          //  mPaint.setStrokeWidth(10);

      }


      @Override
      protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
/*
* 画一个圆,
* 第一个参数为水平方向的中心坐标
* 第二个参数为垂直方向的中心坐标
* 第三个参数为圆的半径
* 第四个参数为我们的画笔
* */
            canvas.drawCircle(MeasureUtil.getScreenSize((Activity) mContext)[0] / 2, 300, radiu, mPaint);

      }

      @Override
      public void run() {
             /*
     * 确保线程不断执行不断刷新界面
     */
            while (true) {
                  try {
            /*
             * 如果半径小于200则自加否则大于200后重置半径值以实现往复
             */
                        if (radiu <= 200) {
                              radiu += 10;

                              // 刷新View
                              postInvalidate();
                        } else {
                              radiu = 0;
                        }

                        // 每执行一次暂停40毫秒
                        Thread.sleep(40);
                  } catch (InterruptedException e) {
                        e.printStackTrace();
                  }
            }
      }
}

Canvas的常用绘制方法:

方法 作用
drawRect() 画矩形
drawCircle() 画圆形
drawArc() 画圆弧
drawBitmap() 画Bitmap
drawOval() 画椭圆
drawRoundRect() 画圆角矩形

好吧,现在我们多少了解了一下自定义View,这仅仅是个开始。

你可能感兴趣的:(Android自定义view初识(一))