对于自定义View的实现,Canvas和Paint两类是很有用的。
这两个类是 android.graphics 包下的两个类,Canvas是画布,Paint是画笔,通过这两者结合一起,就可以绘制出自己需要的View,然后将View加入到布局 xml 中或者在 Java 代码中引用即可。

二、基本步骤

(一)创建一个自定义的MyView继承View
(二)创建MyView的三个构造方法

  • MyView(Context context)
  • MyView(Context context,AttributeSet attributeSet)
  • MyView(Context context, AttributeSet attributeSet,int defStyleAttr)

(三)重写View.onDraw()方法,添加自己的绘制逻辑
(四)在Java代码中引用或者加入到XML布局中

三、具体步骤

(一)创建一个自定义MyView继承View

public class MyView extends View {

(二)创建MyView的三个构造函数

    //当Java代码中创建MyView时调用,如setContentView(new MyView(this))
    public MyView(Context context) {
        super(context);
    //当在XML中引入MyView时候调用
    public MyView(Context context, AttributeSet attributeSet)
        super(context,attributeSet);
    //这个构造函数一般不会主动调用
    public MyView(Context context,AttributeSet attributeSet,int defStyleAttr)
        super(context,attributeSet,defStyleAttr);

Tips:注意三个构造函数的区别,在不同的情况调用不同的构造函数

(三)重写View.onDraw()方法

   @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //这里添加自己的绘制逻辑

(四)在Java代码中引用或者加入到XML布局中

1、 在Java代码中引用

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));

2、在XML布局中引入

XML的布局 activity_main

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <com.example.hasee.clockviewdemo.MyView
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

Java中加载布局activity_mian

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

四、实例(画一个圆)

完整代码如下:

自定义MyView部分

package com.example.hasee.clockviewdemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class MyView extends View {
    private Paint mPaint = new Paint();
    /*三种构造方法*/
    public MyView(Context context) {
        super(context);
        Log.v("MyView","构造函数1 被调用");
        init();
    public MyView(Context context, AttributeSet attributeSet)
        super(context,attributeSet);
        Log.v("MyView","构造函数2 被调用");
        init();
    public MyView(Context context,AttributeSet attributeSet,int defStyleAttr)
        super(context,attributeSet,defStyleAttr);
        Log.v("MyView","构造函数3 被调用");
        init();
    //实现绘制的方法
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //获取控件的宽高
        int width = getWidth();
        int height = getHeight();
        //设置半径
        int raius = Math.min(width,height)/2;
        canvas.drawLine(10,10,100,100,mPaint);
        canvas.drawCircle(width/2,height/2,raidus,mPaint);
        canvas.drawCircle(100,100,20,mPaint);
        Log.v("MyView","onDraw() 被调用");
    //初始化画笔相关设置
    public void init()
        //抗锯齿
        mPaint.setAntiAlias(true);
        //画笔宽度
        mPaint.setStrokeWidth(2f);
        //画笔颜色
        mPaint.setColor(Color.WHITE);
        //画笔填充类型
        mPaint.setStyle(Paint.Style.STROKE);
        Log.v("MyView","init() 被调用,画笔初始化成功");

XML布局activity_main.xml部分(使用XML布局中引入的方式引入MyView)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <com.example.hasee.clockviewdemo.MyView
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:background="#000000"/>
</RelativeLayout>

MainActivity部分

package com.example.hasee.clockviewdemo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

效果如下:
这里写图片描述

五、相关注意事项

(一)注意三种构造函数的调用情况 ,第一和第二类的构造函数是比较常用的,为了避免出现不必要的与构造函数相关的错误,建议最好把三种构造函数都写上;

(二)注意onDraw()方法在每次绘制的时候都会调用,如果动态绘制的话,onDraw会多次调用,因此建议不要在onDraw()方法中进行画布画笔的相关初始化,通常将这些初始化放到构造函数中,记得三个构造函数都要加上;

(三)注意画笔的颜色与背景的搭配。 曾因为将画笔设置为白色而背景颜色没有设置,即默认为白色,导致自定义VIew没有显示出来,后来花了一个上午的时间尝试断点调试、查看官方文档、日志打印查询等方法来排查问题都还是一无所获,直到我看到了Paint.setColor(Color.White),然后将background设置为 #000000(黑色),发现原来是画笔颜色和背景颜色一样导致的结果(刻骨铭心)

一、简述对于自定义View的实现,Canvas和Paint两类是很有用的。 这两个类是 android.graphics 包下的两个类,Canvas是画布,Paint是画笔,通过这两者结合一起,就可以绘制出自己需要的View,然后将View加入到布局 xml 中或者在 Java 代码中引用即可。二、基本步骤(一)创建一个自定义的MyView继承View (二)创建MyView的三个...
ViewView代表屏幕的一个矩形区域,负责绘制这个区域和这个区域的事件处理 View的坐标位置由6个方法来获取View左方的距离getLeft,View右方的距离getRight,View上方的距离getTop,View下方的距离getBottom,宽度getWidth,高度getHeight 实例化1.构造方法1).View(context);在java代码使用的构造器,没有设置任何值,只有
摘要 Android使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0。今天我们主要要了解的是2D相关的,如果你想看3D的话那么可以跳过这篇文章。 大部分2D使用的api都在android.graphics和android.graphics.drawable包。他们提供了图 Android使用图形处理引擎,2D部分是android
setColor(int),设置画笔的颜色 setAlpha(int),设置画笔的透明度 setARGB(int a, int r, int g, int b),设置画笔的颜色,a代表透明度,r,g,b代表颜色值 setAntiAlias(boolean),设置是否使用抗锯齿功能,设置后会平滑一些 setDither(boolean),设定是否使用图像抖动处理,设置后图像更加清晰 setStyle(Style),设置画笔的风格 Style.FILL,实心 Style.FILL_A