Android绘图机制(二)--2D绘图基础

## 前言

每次在讲正事前总要啰嗦几句,其实我也不想,只是文章没得一个开头,看起来就有点不爽,所以大家见谅,不喜欢的可以直接跳过。Android的绘图功能还是十分强大的,只要你有一个敢于创新的心,就没有什么画不出来的,接下来我将,从画图时所使用的工具开始介绍,希望能够帮助到大家,我自己也能够更好的巩固这方面的知识。

绘图工具(一)–画布(canvas)

canvas类相当于一个画布,我们通常把它理解成系统提供给我们的一块内存区(但实际上它只是一套画图的API),并且提供了一套在这个区域操作的一系列方法,着些方法全是用来画图API

以下是canvas常用画图的方法:

  • drawRect(RectF rect, Paint paint) //绘制区域,参数一为RectF一个区域

  • drawPath(Path path, Paint paint) //绘制一个路径,参数一为Path路径对象

  • drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) //贴图,参数一就是我们常规的Bitmap对象,参数二是源区域(这里是bitmap),参数三是目标区域(应该在canvas的位置和大小),参数四是Paint画刷对象,因为用到了缩放和拉伸的可能,当原始Rect不等于目标Rect时性能将会有大幅损失。

  • drawLine(float startX, float startY, float stopX, float stopY, Paintpaint) //画线,参数一起始点的x轴位置,参数二起始点的y轴位置,参数三终点的x轴水平位置,参数四y轴垂直位置,最后一个参数为Paint 画刷对象。

  • drawPoint(float x, float y, Paint paint) //画点,参数一水平x轴,参数二垂直y轴,第三个参数为Paint对象。

  • drawText(String text, float x, floa ty, Paint paint) //渲染文本,Canvas类除了上面的还可以描绘文字,参数一是String类型的文本,参数二x轴,参数三y轴,参数四是Paint对象。

  • drawOval(RectF oval, Paint paint)//画椭圆,参数一是扫描区域,参数二为paint对象;

  • drawCircle(float cx, float cy, float radius,Paint paint)// 绘制圆,参数一是中心点的x轴,参数二是中心点的y轴,参数三是半径,参数四是paint对象;

  • drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//画弧,参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,参数二是起始角(度)在电弧的开始,参数三扫描角(度)开始顺时针测量的,参数四是如果这是真的话,包括椭圆中心的电弧,并关闭它,如果它是假这将是一个弧线,参数五是Paint对象;

除此以外还有一些方法特别有用:

  • Canvas.save() 将之前所有已经绘制的图像保存起来,让后续的操作好像在一个新的图层中操作一样

  • Canvas.restore() 该方法可以理解为PS中的合并图层操作,作用是将save()之前后的图像进行合并

  • Canvas.translate(x,y) 该方法的意思是将坐标系的原点移动到(x,y) 处,之后所有的操作都将以(x,y)为原点进行

  • Canvas.rotate() 将坐标系选装一定的角度

绘图工具(二)–画笔(Paint)

系统通过Canvas对象来提供绘图方法,但是还缺少一个绘图的笔来完成整个绘图的操作。可以看到Canvas的很多方法的最后都需要传入一个Paint对象,由此可见Paint画笔的重要性,Paint对象在画图中主要起到对线条颜色,效果,风格的控制上。接下来是一些常用的Paint的属性和对应功能。

  • setAntiAlias(); 设置画笔的锯齿效果

  • setColor(); 设置画笔的颜色

  • setARGB(); 设置画笔的A , R , G , B值

  • setAlpha(); 设置画笔的Alpha值(透明度 取值0~255之间,越小透明度越高)

  • setTextSize(); 设置字体的尺寸(有时在绘图中也需要绘画字体)

  • setStyle(); 设置画笔的风格(空心或者实心)

  • setStrokeWidth(); 设置画笔的宽度

绘图工具(三)–路径(Path)

path类用于记录一些路径,可以当作是看不见的线,也可以用作记录手指接触屏幕滑动的路径,绘制复杂图形轮廓等等,在绘图和动画中,path类都发挥着重要的作用。

构造方法:
创建一个含有src的path对象(目前还没有用过)

    public Path(Path src) {
        long valNative = 0;
        if (src != null) {
            valNative = src.mNativePath;
            isSimplePath = src.isSimplePath;
            if (src.rects != null) {
                rects = new Region(src.rects);
            }
        }
        mNativePath = init2(valNative);
    }

接下来列举一些常用的方法

  • moveTo(float x , float y) 移动绘制起点到(x,y)的位置开始绘制

  • lineTo(float x , float y) 连接从起点到(x,y)的直线,默认起点为(0,0)

  • rMoveTo(float dx, float dy) 在上一次绘制的终点的基础上,移动dx,dy的距离得到新的起点。(这里的dx , dy为移动的距离)

  • rLineTo(float dx , float dy)在上一次绘制的基础上,移动dx , dy的连线。和lineTo()的效果一样,只是起点是上一次绘制的终点,坐标表示的是距离。

  • quadTo(float x1 , float y1 , float x2 , float y2) 根据两个点你控制,绘制贝塞尔曲线

  • cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)根据三点控制,绘制贝尔塞曲线

  • arcTo(RectF oval, float startAngle, float sweepAngle)用于绘制圆弧

  • addRect(float left, float top, float right, float bottom, Direction dir)添加矩形

  • addOval(RectF oval, Direction dir) 添加一个闭环圆环路径

  • addCircle(float x, float y, float radius, Direction dir) 添加一个圆形路径

  • addRoundRect(RectF rect, float rx, float ry, Direction dir)添加一个圆角矩形路径

  • offset(float dx, float dy, Path dst) 通过dx,dy移动路径,如图dst为null则修改原路径,即src

  • reset() 清空当前路径中的设置信息

  • rewind() 清空当前path,清空所有的直线曲线,但保留其数据结构,方便重用

注:
Path.Direction 用来指定添加到path中的闭合图形的绘制方向(两个值,分别为顺时和逆时)

  • CW 表示顺时针

  • CCW表示逆时针

FillType表示填充模式:

  • FillType.WINDING 默认值,当两个图形香蕉,正常相交情况显示

  • FillType.EVEN_ODD 取path所在并不相交的区域

  • FillType.INVERSE_WINDING 取path的外部区域

  • FillType.INVERSE_EVEN_ODD 取path外部和相交区域

(INVERSE就是取反的意思)下面是几个填充结果

FillType.WINDING
这里写图片描述

FillType.EVEN_ODD
这里写图片描述

FillType.INVERSE_WINDING
这里写图片描述

INVERSE_EVEN_ODD
这里写图片描述

接下来通过一个实例来巩固一下这个绘制的内容。我们要做的是一个时钟的图形,如下图:

这里写图片描述

首先分析这个图形所需要绘制的元素有:表盘,刻度,指针,数字

首先我们选择绘制表盘,表盘就是一个大圆盘,直接调用canvas.drawCircle()方法绘制一个圆就行了,关键是定圆心和半径,这里直接确定在屏幕中间了

        private Paint paintCircle;
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();//获取屏幕宽高
        paintCircle = new Paint();//初始化画笔
        paintCircle.setColor(Color.BLACK);//设置颜色
        paintCircle.setAntiAlias(true);
        paintCircle.setStyle(Paint.Style.STROKE);
        paintCircle.setStrokeWidth(5);//设置笔宽
        canvas.drawCircle(mWidth/2 , mHeight/2 , mWidth/2 , paintCircle);//画圆

完成了表盘后就开始画刻度线,这个也不难就是一条线段,只要确定了两端点的坐标就可以轻松搞定,关键问题是斜着的线段如何获取坐标呢,这里利用到了旋转坐标系,看如下代码:

        paintDegree = new Paint();
        paintCircle.setStrokeWidth(3);
        for(int i = 0 ; i < 24 ; i++){
            if(i == 0 || i == 6 || i == 12 || i == 18){//正的时刻直接画出
                paintDegree.setStrokeWidth(5);
                paintDegree.setTextSize(30);
                canvas.drawLine(mWidth/2, mHeight/2 - mWidth/2,mWidth/2,mHeight/2 - mWidth/2 +60,paintDegree );
                String degree = String.valueOf(i);
                canvas.drawText(degree,mWidth/2 - paintDegree.measureText(degree)/2, mHeight/2 - mWidth/2 + 90,paintDegree);
            }else{//斜着的时刻绘制
                paintDegree.setStrokeWidth(3);
                paintDegree.setTextSize(15);
                canvas.drawLine(mWidth/2, mHeight/2 - mWidth/2,mWidth/2,mHeight/2 - mWidth/2 +60,paintDegree);
                String degree = String.valueOf(i);
                canvas.drawText(degree,mWidth/2 - paintDegree.measureText(degree)/2, mHeight/2 - mWidth/2 + 90,paintDegree);
            }
            canvas.rotate(15 ,mWidth/2 , mHeight/2);//旋转坐标系
        }

最后绘制时针,计时从原点开始的两条线段

        paintHour = new Paint();
        paintHour.setStrokeWidth(20);
        Paint paintMinute = new Paint();
        paintMinute.setStrokeWidth(10);
        canvas.save();//保存画布
        canvas.translate(mWidth/2 , mHeight/2);
        canvas.drawLine(0,0,100,100,paintHour);
        canvas.drawLine(0,0,100,200,paintMinute);
        canvas.restore();//组合画布

到此为止就完成了整个绘画的过程,当然其中没有用到path,不过不要紧,在后续的动画讲解中,path会有很多作用的,还有前面有一篇介绍SurfaceView使用的文章中,就有使用path来记录手指在屏幕滑动的轨迹。绘图机制中的绘制就到此结束了,当然还有3D的绘图,我自己还在学习当中~希望这篇文章能够帮助到大家~我们一起加油~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值