canvas的使用

1:画圆
canvas.drawCircle(width / 2, height / 2, radius, mPaint);//绘制圆形,第一个参数是圆心的x坐标,第二个参数是圆心的y坐标,第三个参数是半径,单位都是像素
2:画矩形canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),paint);//这里绘制出来的矩形是实心的矩形,而不是空心的矩形线条,因为paint设置的style是Paint.Style.FILL,前四个参数的具体含义请看下图
image.png
3:canvas.save()和canvas.restore()的区别
@Override
    protected void onDraw(Canvas canvas) {
        canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),paint);
        canvas.drawRect(10,10,getMeasuredWidth()-10,getMeasuredHeight()-10,paint1);
        canvas.save();
        canvas.translate(10,0);
        canvas.restore();
        super.onDraw(canvas);
    }
区别是:当调用save方法后,就将canvas的位置和角度记录下来了,然后接下来就可以进行画布的平移,旋转之类的位置变化操作,也可以进行画图操作,不过此时所画的图是在进行了位置变化操作之后的canvas上进行的,如果要还原上一次保存的canvas的位置的话,就调用restore方法,这时canvas的位置就回到了上一次save时的状态了。
4,画圆弧:drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)

oval :指定圆弧的外轮廓矩形区域。
startAngle: 圆弧起始角度(x轴的正右的方向,是0度的位置),单位为度。
sweepAngle: 圆弧扫过的角度,顺时针方向为正角度,单位为度
useCenter: 如果为True时,用来绘制扇形,如果为false时,用来绘制弧形。
paint: 绘制圆弧的画板属性,如颜色,是否填充等。

paint.setStyle(Paint.Style.FILL);
canvas.drawArc(200,100,800,500,180,60,false,paint);
以上两句代码画出的形状是
5,画笔的一些方法

1:用paint的时候有三种Style,分别是
Paint.Style.STROKE 只绘制图形轮廓(描边)
Paint.Style.FILL 只绘制图形内容 ,默认是Paint.Style.FILL
Paint.Style.FILL_AND_STROKE 既绘制轮廓也绘制内容


image.png

2:mPaint.setStrokeWidth(40);//用来设置画笔的宽度

6,设置画布的颜色,这类颜色填充方法一般用于在绘制之前设置底色,或者在绘制之后为界面设置半透明蒙版。
        canvas.drawColor(Color.RED);
        canvas.drawARGB(100,100,100,100);
        canvas.drawRGB(100,100,100);
7,设置线条的宽度,在STROKE和FILL_AND_STROKE下使用
paint.setStrokeWidth(10);//设置线条宽度为10像素
8,在绘制的时候,往往需要开启抗锯齿来让图形和文字的边缘更加平滑
        paint=new Paint(Paint.ANTI_ALIAS_FLAG);//静态开启抗锯齿
        paint.setAntiAlias(true);//动态开启抗锯齿
9,绘制一个点,前两个参数是x,y坐标,点的大小可以通过paint.setStrokeWidth来设置,点的形状可以通过paint.setStrokeCap来设置,其中,SQUARE或BUTT画出来是方形的点,ROUND画出来是圆形的点。
canvas.drawPoint(100,100,paint);
10,画椭圆
canvas.drawOval(100,100,200,500,paint);
11,画线,由于直线不是封闭图形,所以paint.setStyle对直线没有影响,canvas.drawLine是画一条线,可以用canvas.drawLines批量画线
canvas.drawLine(200,200,400,400,paint);
12,画圆角矩形,第五个和第六个参数是矩形的每个圆角的横向半径和纵向半径
canvas.drawRoundRect(200,300,400,500,80,80,paint);
13,根据path画图形
canvas.drawPath(path, paint);

其中,Path对象有如下

第一组,add...方法(添加完整封闭图形,除了addPath())

        path.addCircle(300,300,200, Path.Direction.CW);//添加圆
        //path.addOval();//添加椭圆
        //path.addRect();//添加矩形
        //path.addRoundRect();添加圆角矩形
        //path.addPath();添加path

第二组,...To方法(画直线或者曲线)

        //lineTo和rLineTo画直线
        paint.setStyle(Paint.Style.STROKE);//如果参数是Paint.Style.FILL,那么画出来的是个三角形,和上面的那个画圆弧的一样,将画笔style设置为FILL
        path.lineTo(100,100);//参数是绝对坐标,由当前位置(0,0)向(100,100)画一条直线
        path.rLineTo(100,0);//参数是相对坐标,由当前位置(100,100)向正右方100像素的位置画一条直线
        canvas.drawPath(path, paint);

        //moveTo移动原点位置
        paint.setStyle(Paint.Style.STROKE);
        path.lineTo(100,100);//相对于原点(0,0)画直线到点(100,100)
        path.moveTo(200,100);//此时原点坐标为(200,100)
        path.lineTo(200,0);//相对于原点(200,100)画直线到点(200,0),注意这个(200,0)点还是以(0,0)为原点的(200,0)点,因为用的是lineTo,如果是rLineTo()则原点为(200,100)
        canvas.drawPath(path, paint);

        //arcTo画弧线
        paint.setStyle(Paint.Style.STROKE);
        path.lineTo(100,100);
        path.arcTo(100,100,300,300,-90,90,false);//第七个参数为直线连线连到弧形起点,true为无痕迹,false为有痕迹,如果没有path.lineTo(100,100);这句
        //代码的话,true和false的效果是一样的
        canvas.drawPath(path, paint);

        //addArc画弧线
        paint.setStyle(Paint.Style.STROKE);
        path.lineTo(100,100);
        path.addArc(100,100,300,300,-90,90);//path.addArc(100,100,300,300,-90,90)相当于path.arcTo(100,100,300,300,-90,90,true),addArc()相当于arcTo()的第七个参数为true的简化版
        canvas.drawPath(path, paint);

第三,Path的close方法,不是所有的子图形都需要使用path的close()来封闭的,当paint的style是FILL或者是FILL_AND_STROKE时,Path会自动封闭子图形,这就是上面画弧和画两条线,如果设置为FILL,画出来的是填充的弧和三角形的原因。

        paint.setStyle(Paint.Style.FILL);
        path.moveTo(100,100);
        path.lineTo(200,100);
        path.lineTo(150,150);
        canvas.drawPath(path, paint);//这里只绘制了两条边,但由于style是FILL,所以绘制时会自动封口

第四,Path的setFillType方法,对于添加子图形类方法(如path.addCircle(),path.addRect())的方向,由方法的dir参数来控制,而对于画线类的方法(如path.lineTo(),path.arcTo())的方向就是图形的方向

        paint.setStyle(Paint.Style.FILL);
        path.addCircle(300,300,200, Path.Direction.CCW);//CW顺时针,CCW逆时针
        path.addCircle(300,300,100, Path.Direction.CW);
        path.setFillType(Path.FillType.INVERSE_WINDING);//EVEN_ODD是如果是奇数就绘制,也就是说如果两个图形有部分重合,那么重合的那部分就不绘制,绘制剩下的
        //WINDING是按方向进行相加的,顺时针方向+1,逆时针方向-1,最后为0的那部分不绘制,绘制剩下的
        //INVERSE_EVEN_ODD就是将EVEN_ODD反过来
        //INVERSE_WINDING就是将WINDING反过来
        canvas.drawPath(path,paint);
来个图片,通俗易懂
14,画Bitmap
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
...
canvas.drawBitmap(bitmap,100,100,paint);
15,绘制文字
        paint.setTextSize(100);//设置文字的大小
        canvas.drawText("你好啊",200,200,paint);

以前记录过的

        Paint a=new Paint();
        a.setColor(Color.RED);
        //a.setAlpha(100);
        //a.setStyle(Style.FILL_AND_STROKE);//设置画笔的风格
        //a.setStrokeWidth(33);//设置空心线宽
        a.setTextSize(34);//设置画笔字体的大小
        //a.setTypeface(Typeface.DEFAULT_BOLD);//设置字体样式
        //a.setTextScaleX(55);//设置比例因子,以一为标准
        //a.setARGB(40, 45, 88, 66);//设置字体的颜色
        //a.setUnderlineText(true);//设置下划线
        //a.setTextSkewX(3);//设置倾斜因子,以零为标准
        canvas.drawColor(Color.GREEN);//设置背景颜色
        //canvas.drawText("n好啊", 70, 90, a);
        ///canvas.drawCircle(33, 22, 44, a);
        //canvas.drawLine(33, 44, 11, 22, a);
        //canvas.drawPoint(44, 55, a);
        //canvas.drawRoundRect(new RectF(55,277,488,499), 35, 22, a);//绘制圆角矩形
        //canvas.drawOval(new RectF(33,333,222,444), a);//绘制椭圆形
        //Path ab=new Path();
        //ab.moveTo(33, 44);
        //ab.lineTo(77, 88);
        //ab.lineTo(76, 55);
        //canvas.drawPath(ab, a);//绘制任意多边形
        //canvas.drawArc(new RectF(33,44,333,444), 66, 55, true, a);//绘制圆弧
        //Bitmap ac=((BitmapDrawable)getResources().getDrawable(R.drawable.ic_launcher)).getBitmap();
        //canvas.drawBitmap(ac, 444, 44, a);//绘制图像
        
        //canvas.clipRect(44, 66, 222, 330);//裁剪指定的区域
        //canvas.drawColor(Color.BLUE);
        //canvas.drawText("旋转字", 43, 333, a);
        //canvas.save();
        //canvas.rotate(60,43,333);
        //canvas.drawText("旋转字", 43, 333, a);
        //canvas.restore();//关于画布锁定和解锁,旋转的例子

-----------------------------------------------------------------------------------

android群英传中对canvas的介绍

1:Canvas.save(),Canvas.restore(),Canvas.translate(),Canvas.rotate()这四个方法的介绍如下:

Canvas.save()这个方法,从字面上可以理解为保存画布,它的作用就是将之前的所有已绘制图像保存起来,让后续的操作就好像在一个新的图层上操作一样,这一点点与photoshop中的图层理解基本一致。
Canvas.restore()这个方法,则可以理解为photoshop中的合并图层操作,它的作用是将我们在save()之后绘制的所有图像与save()之前的图像进行合并。
translate()和rotate()方法,就是在调用translate(x,y)方法之后,将原点(0,0)移动到(x,y)。之后的所有绘图操作都将以(x,y)为原点执行。同理totate()方法也是一样的,它将坐标系旋转了一定的角度。

2:Layer图层

在android中通过调用saveLayer()方法,saveLayerAlpha()方法创建一个图层,使用restore()方法,restoreToCount()方法合并所有图层。创建图层的时候,后面所有的操作都发生在这个图层上。saveLayerAlpha()的第五个参数的取值如果是0比表示完全透明,127表示半透明,255表示完全不透明。示例代码如下:

        canvas.drawCircle(300,300,200,paint);
        canvas.saveLayerAlpha(0,0,600,600,127);
        paint.setColor(Color.GREEN);
        canvas.drawCircle(300,300,300,paint);
        canvas.restore();

图如下所示:


3:PorterDuffXfermode(参考文章:https://www.jianshu.com/p/0f64daf202f2)


示例代码如下:

...
        canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),paint);//必须要新建一个图层才能看到混合后的效果了
        canvas.drawCircle(0,0,bitmap.getWidth()/2,paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap,0,0,paint);
        paint.setXfermode(null);// 还原混合模式
        canvas.restore();//合并图层
...

效果如下:


4:Shader,着色器,渲染器,Shader包括:BitmapShader(位图Shader),LinearGradient(线性Shader),RadialGradient(光速Shader),SweepGradient(梯度Shader),ComposeShader(混合Shader)

4.1:BitmapShader的使用,填充模式有三种CLAMP(拉伸),REPEAT(重复),MIRROR(镜像),示例代码如下:

 paint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
        canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, canvas.getWidth() / 2 > canvas.getHeight() / 2 ? canvas.getHeight() / 2 : canvas.getWidth() / 2, paint);

结果如下所示:



4.2:LinearGradient的使用,示例代码如下:

 paint.setShader(new LinearGradient(0,0,canvas.getWidth(),canvas.getHeight(),Color.BLUE,Color.GREEN, Shader.TileMode.CLAMP));
        canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, canvas.getWidth() / 2 > canvas.getHeight() / 2 ? canvas.getHeight() / 2 : canvas.getWidth() / 2, paint);

结果如下所示:


小技巧:Marix.setScale(1F,-1F)可以实现图片的垂直翻转。

5:PathEffect

5.1:DiscretePathEffect,使用这个效果之后,线段上就会产生许多杂点

        paint.setPathEffect(new DiscretePathEffect(3f,5f));
        Path path=new Path();
        path.moveTo(0,canvas.getHeight()/2);
        path.lineTo(canvas.getWidth()/3,0);
        path.lineTo(canvas.getWidth()/3*2,canvas.getHeight());
        path.lineTo(canvas.getWidth(),0);
        canvas.drawPath(path,paint);

效果图如下:



5.2:DashPathEffect,这个效果可以用来绘制虚线,用一个数组来设置各个点之间的间隔,此后绘制虚线时就重复这样的间隔进行绘制,另一个参数则用来控制绘制时数组的一个偏移量,通常可以通过设置值来实现路径的动态效果。

  paint.setPathEffect(new DashPathEffect(new float[]{20,10,5,10},0));

效果图如下:



5.3:PathDashPathEffect,这个效果和DashPathEffect效果类似,只不过它的功能更加强大,可以设置显示点的图形,即方形点的虚线,圆形点的虚线。

        Path path1=new Path();
        path1.addRect(0,0,8,8,Path.Direction.CCW);
        paint.setPathEffect(new PathDashPathEffect(path1,12f,0,PathDashPathEffect.Style.ROTATE));

效果图如下:



5.4:CornerPathEffect,就是将拐角处变得圆滑,具体圆滑的程度,则由参数决定。

 paint.setPathEffect(new CornerPathEffect(30));

效果图如下:



5.5:ComposePathEffect,将任意两种路径特效组合起来形成一个新的效果。

        PathEffect pathEffect=new CornerPathEffect(30);
        PathEffect pathEffect1=new DashPathEffect(new float[]{20,10,5,10},0);
        paint.setPathEffect(new ComposePathEffect(pathEffect,pathEffect1));

效果图如下:



5.6:SumPathEffect,将任意两种路径特效组合起来形成一个新的效果。

        PathEffect pathEffect=new CornerPathEffect(30);
        PathEffect pathEffect1=new DashPathEffect(new float[]{20,10,5,10},0);
        paint.setPathEffect(new SumPathEffect(pathEffect,pathEffect1));

效果图如下:


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容