自定义View学习笔记04—Canvas的绘制图形

前面通过深入学习,通过3篇笔记详细的记录了自定义View的一些基础知识,从这篇开始正式进入自定义View的大门。

  • TODO:Canvas可以绘制的对象有:弧线(arcs)、填充颜色(argb和color)、 Bitmap、圆(circle和oval)、点(point)、线(line)、矩形(Rect)、图片(Picture)、
  •  圆角矩形 (RoundRect)、文本(text)、顶点(Vertices)、路径(path)。
    
  • TODO:Canvas位置转换的方法:rorate、scale、translate、skew(扭曲)等
  • TODO:Canvas 还提供了保存和回滚属性的方法(save和restore),比如你可以先保存目前画纸的位置(save),
  •  然后旋转90度,向下移动100像素后画一些图形,画完后调用restore方法返回到刚才保存的位置
    

本文先讲Canvas绘制填充颜色(argb和color)、弧线(arcs)、圆(circle和oval)、点(point)、线(line)、(圆角)矩形Rect/RoundRect,下一篇笔记再讲图片(Picture)、文本(text)、顶点(Vertices)、路径(path)、Bitmap。

我们先从自定义View的常见步骤开始:

public class MyCanvas extends View {
    public static int widthSize = 0;
    public static int heightSize = 0;
    public static Paint mPaint = null;
    private String textContent;
    private float textSize = 0f;
    private float minTextSize = 16f;
    private Context mContext;
    
    public String getTextContent() {
        return textContent;
    }

    public void setTextContent(String textContent) {
        this.textContent = textContent;
    }

    public MyCanvas(Context context) {
        super(context);
        mContext = context;
        if(mPaint == null){
	        initPaint();//实例化画笔对象;
        }
    }

    public MyCanvas(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        if(mPaint == null){
			initPaint();//实例化画笔对象;			
		}
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int heiSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int widSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heiSpecSize = MeasureSpec.getSize(heightMeasureSpec);
        DisplayMetrics metrics = getResources().getDisplayMetrics();
        if (widSpecMode == MeasureSpec.AT_MOST && 
	        heiSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(metrics.widthPixels, 
	            DisplayUtils.dpToPx(mContext, 300));
        }else if(widSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(metrics.widthPixels, heiSpecSize);
        }else if(heiSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(widthMeasureSpec, 
	            DisplayUtils.dpToPx(mContext, 300));
        }
    }
	
	//int w, int h:自定义View的最终大小
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(widthSize, heightSize, oldw, oldh);
        widthSize = w;
        heightSize = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
		//自定义View的各方法可以根据需要在这里调用,如:
		drawColor(canvas);//绘制纯色(界面为某个指定的颜色)
    }
}

我们再来看看自定义的View如何在Activity里面使用:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getSupportActionBar().hide();
    setContentView(R.layout.activity_canvas);
    LinearLayout llCanvas = (LinearLayout) findViewById(R.id.llCanvas);
    MyCanvas mCanvas = new MyCanvas(CanvasActivity.this);
    llCanvas.addView(mCanvas);
}

现在我们正式开始自定义View的基础学习:

1、绘制纯色(为界面指定某个颜色):drawColor(int color)

private void drawColor(Canvas canvas){
    canvas.drawColor(Color.parseColor("#99ff00ff"));
    //或者:
    //canvas.drawColor(Color.BLUE);
}

在MyCanvas的onDraw()方法里调用该方法,效果如下:
绘制纯色/为界面指定某个颜色

2、绘制点(包括一系列的点):drawPoint(float x, float y, Paint paint)、
drawPoints(float[] pts,Paint paint)

private void drawPoint(Canvas canvas){
    //一系列的点
    float array = new float[]{28,28,56,56,84,84,112,112,140,140}
    canvas.drawPoints(array , mPaint);
    mPaint.setColor(Color.parseColor("#0000ff"));
    mPaint.setStrokeWidth(12);
    //单个点
    canvas.drawPoint(500, 500, mPaint);
}

在MyCanvas的onDraw()方法里调用该方法,效果如下:
绘制点

3、绘制直线(包含一系列的):drawLine(float startX, float startY, float stopX, float stopY, Paint paint)、drawLines(float[] pts, Paint paint)

private void drawLine(Canvas canvas){
    mPaint.setStrokeWidth(5f);
    mPaint.setColor(Color.BLACK);
    canvas.drawLine(100,220,480,230, mPaint);
    canvas.drawLines(new float[]{300,320,420,430,
            420,430,580,600,
            580,600,328,400,
            328,400,700,650},mPaint);
}

注意:数组float[] pts的长度必须是4的整倍数,否则,最后一条直线无法绘制。
在MyCanvas的onDraw()方法里调用该方法,效果如下:
绘制直线

4、绘制矩形(有三个方法,结果都一样):drawRect(float left, float top, float right, float bottom, Paint paint)、drawRect(RectF rect, Paint paint)、drawRect(RectF rect, Paint paint)。

private void drawRect(Canvas canvas){
    //方法一:
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setColor(Color.BLACK);
    canvas.drawRect(100,100,500,500,mPaint);
    //方法二:
    Rect rect = new Rect(150,150,450,450);
    mPaint.setColor(Color.GREEN);
    canvas.drawRect(rect, mPaint);
    //方法三:
    RectF rectF = new RectF(200,200,400,400);
    mPaint.setColor(Color.CYAN);
    canvas.drawRect(rectF, mPaint);        
}

注意:Rect和RectF两种的区别:最大的区别就是精度不同,Rect是int的,而RectF是float的;两种提供的方法也稍微存在差别,详见官方文档。

在MyCanvas的onDraw()方法里调用该方法,效果如下:
绘制矩形

5、绘制圆角矩形(其实既可以画圆角矩形,也可以画椭圆,还有画圆):
drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,Paint paint) 、drawRoundRect(RectF rect, float rx, float ry, Paint paint)。

private void drawRoundRect(Canvas canvas){
    //绘制圆角矩形方法一:
    RectF rectF1 = new RectF(550,550,880,880);
    //两个40的含义:圆角在X、Y两个方向上的半径
    canvas.drawRoundRect(rectF1,40,40,mPaint);
    //绘制圆角矩形方法二:
    mPaint.setColor(Color.WHITE);
    canvas.drawRoundRect(600, 600, 850, 850, 40, 40, mPaint);
	//画圆(条件:在正方形的基础上绘制才行):
	mPaint.setColor(Color.YELLOW);
	//圆角在X、Y两个方向上的半径分别为矩形(实际是正方形)长和宽的一半
	RectF rectF3 = new RectF(150,150,450,450);
	canvas.drawRoundRect(rectF3,150,150,mPaint);

    //画椭圆1(条件:在矩形的基础上绘制才行):
    mPaint.setColor(Color.GRAY);
    RectF rectF4 = new RectF(200,150,400,450);
    canvas.drawRoundRect(rectF4,100,150,mPaint);

    //画椭圆2(条件:在矩形的基础上绘制才行):
    mPaint.setColor(Color.BLACK);
    RectF rectF5 = new RectF(200,250,400,350);
    canvas.drawRoundRect(rectF5,100,50,mPaint);
}

在MyCanvas的onDraw()方法里调用该方法,效果如下:
绘制圆角矩形

6、绘制圆(含圆环):drawCircle(float cx, float cy, float radius, Paint paint)

private void drawCircle(Canvas canvas){
    //绘制圆环的两种方式:
    //方式一:mPaint画笔style设为描边STROKE,画笔的width加大
    //但这样有个缺陷:mPaint的width会均分在圆的内外两侧,
    //使得所画出的圆比预期的大;比如下方:
    //圆的半径150,mPaint的width = 100,画出来的结果是mPaint的width
    //有一半(50)分布在圆半径150的外侧,另一半分布在内侧,
    //这样画出来的圆直径比预期大了50(mPaint的width的一半),因此该方法尽可能少用;
    mPaint.setColor(Color.GREEN);
    mPaint.setStrokeWidth(10);
    mPaint.setStyle(Paint.Style.STROKE);
    canvas.drawCircle(200, 200, 100, mPaint);

    mPaint.setColor(Color.RED);
	//mPaint.setStrokeWidth(1);
    mPaint.setStyle(Paint.Style.FILL);
    canvas.drawCircle(400, 400, 150, mPaint);
    //方式二:画两个半径不一样的同心圆
    mPaint.setColor(Color.WHITE);
    mPaint.setStyle(Paint.Style.STROKE);
    canvas.drawCircle(400, 400, 100, mPaint);

    //画圆
    int CircleCenter = widthSize < heightSize ? widthSize : heightSize;
    mPaint.setAntiAlias(true);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeWidth(8);
    mPaint.setColor(Color.BLACK);
    canvas.drawCircle(widthSize/2, heightSize/2, (CircleCenter*4)/10, mPaint);
}

在MyCanvas的onDraw()方法里调用该方法,效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lwPnB5XN-1589614546052)(https://img-blog.csdn.net/20171225181022897?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFveXVlZ29uZ3pp/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)]

7、绘制圆弧drawArc():drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint);

private void drawArc(Canvas canvas){
    //绘制正方形背景
    RectF rectF01 = new RectF(50,50,250,250);
    mPaint.setColor(Color.parseColor("#00ff00"));
    mPaint.setStyle(Paint.Style.FILL);
    canvas.drawRect(rectF01, mPaint);
    //绘制圆弧
    mPaint.setColor(Color.GRAY);
    canvas.drawArc(rectF01, 0, 160, false, mPaint);
    //绘制长方形背景
    RectF rectF02 = new RectF(300,300,700,580);
    mPaint.setColor(Color.parseColor("#00ff00"));
    canvas.drawRect(rectF02, mPaint);
    //绘制圆弧
    mPaint.setColor(Color.GRAY);
    canvas.drawArc(rectF02, 0, 160, true, mPaint);
}

总结:
1、false:不用圆心,直接是连接圆弧的起点和终点,形成的一个玄弧封闭区域,true:用到圆心,是链接圆弧的起点、中心/圆心、圆弧终点所形成的一个扇形。如下图的上半部分
2、画圆弧,则需要RectF对应的矩形背景为正方形,画椭圆弧,则需要RectF对应的矩形背景为长方形。如下图的下半部分。
在MyCanvas的onDraw()方法里调用该方法,效果如下:
圆弧

Canvas的基本图形绘制先讲到这里,更深层次的图形绘制我们下一节继续学习。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值