canvas类:
- 1
- 2
- 1
- 2
这个类相当于一个画布,你可以在里面画很多东西;
我们可以把这个Canvas理解成系统提供给我们的一块内存区域(但实际上它只是一套画图的API,真正的内存是下面的Bitmap),而且它还提供了一整套对这个内存区域进行操作的方法,所有的这些操作都是画图API。也就是说在这种方式下我们已经能一笔一划或者使用Graphic来画我们所需要的东西了,要画什么要显示什么都由我们自己控制。
这种方式根据环境还分为两种:一种就是使用普通View的canvas画图,还有一种就是使用专门的SurfaceView的canvas来画图。两种的主要是区别就是可以在SurfaceView中定义一个专门的线程来完成画图工作,应用程序不需要等待View的刷图,提高性能。前面一种适合处理量比较小,帧率比较小的动画,比如说象棋游戏之类的;而后一种主要用在游戏,高品质动画方面的画图。
下面是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, floaty, 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对象;
还要理解一个paint类:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
案例
看一下效果图:
CustomActivity.java
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
重要的类自定义View组件要重写View组件的onDraw(Canvase)方法,接下来是在该 Canvas上绘制大量的几何图形,点、直线、弧、圆、椭圆、文字、矩形、多边形、曲线、圆角矩形,等各种形状!
DrawView.Java
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
参考链接
Android利用canvas画各种图形(点、直线、弧、圆、椭圆、文字、矩形、多边形、曲线、圆角矩形) - 任海丽(3G/移动开发) - 博客频道 - CSDN.NET
道Canvas可以绘制的对象有:
弧线(arcs)、填充颜色(argb和color)、 Bitmap、圆(circle和oval)、点(point)、线(line)、矩形(Rect)、图片(Picture)、圆角矩形 (RoundRect)、文本(text)、顶点(Vertices)、路径(path)。通过组合这些对象我们可以画出一些简单有趣的界面出来,但是光有这些功能还是不够的,如果我要画一个仪表盘(数字围绕显示在一个圆圈中)呢? 幸好Android还提供了一些对Canvas位置转换的方法:rorate、scale、translate、skew(扭曲)等,而且它允许你通过获得它的转换矩阵对象(getMatrix方法,不知道什么是转换矩阵?看这里) 直接操作它。这些操作就像是虽然你的笔还是原来的地方画,但是画纸旋转或者移动了,所以你画的东西的方位就产生变化。为了方便一些转换操作,Canvas 还提供了保存和回滚属性的方法(save和restore),比如你可以先保存目前画纸的位置(save),然后旋转90度,向下移动100像素后画一些图形,画完后调用restore方法返回到刚才保存的位置。下面我们就演示下canvas的一些简单用法:
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
效果
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
效果
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
两图对比我们可以发现,当 drawArcs(rect,startAngel,sweepAngel,useCenter,paint)中的useCenter为false时,弧线区域是用弧线开始角度和结束角度直接连接起来的,当useCenter为true时,是弧线开始角度和结束角度都与中心点连接,形成一个扇形。
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
canvas.drawColor是直接将View显示区域用某个颜色填充满。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
Canvas.drawOval:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
canvas.drawPosText:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
canvas.drawRect:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
rect的参数是表示左上角与右下角的坐标
canvas.drawRoundRect:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
canvas.drawPath:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
canvas.drawTextOnPath:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
位置转换方法,canvas.rorate和canvas.translate:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
上面几个例子基本已经将常用的canvas.draw*方法测试过了,我们结合一些事件,做一些有用户交互的应用:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
当用户点击时将出现一个小点,拖动时将画出一条用细点组成的虚线:
参考链接
Android Canvas绘图详解(图文) - 泡在网上的日子
Android利用canvas画各种图形(点、直线、弧、圆、椭圆、文字、矩形、多边形、曲线、圆角矩形) - 任海丽(3G/移动开发) - 博客频道 - CSDN.NET
完成
前言:厚积方能薄发
相关文章:
《Android自定义控件三部曲文章索引》: http://blog.csdn.net/harvic880925/article/details/50995268
经过前几篇,我们基本把paint和canvas的基本用法就看完了,今天我们来个大汇总,列举一个paint的所有函数,然后一个一个的过。经过这几篇,你将能学会paint中所有处理函数的用法。
一、基本用法
1、概述
我们先来看一下paint中基本设置的函数都有哪些:reset()
重置画笔
setColor(int color)
给画笔设置颜色值
setARGB(int a, int r, int g, int b)
同样是设置颜色,但是利用ARGB分开设置
setAlpha(int a)
设置画笔透明度
setStyle(Paint.Style style)
设置画笔样式,取值有
- Paint.Style.FILL :填充内部
- Paint.Style.FILL_AND_STROKE :填充内部和描边
- Paint.Style.STROKE :仅描边
设置画笔宽度
setAntiAlias(boolean aa)
设置画笔是否抗锯齿
上面这些函数,我们在前面几篇已经详细讲过了,难度也都不大,不再细讲。下面几个函数我们是没有讲到过的,下面做下补充
setStrokeCap(Paint.Cap cap)
设置线冒样式,取值有Cap.ROUND(圆形线冒)、Cap.SQUARE(方形线冒)、Paint.Cap.BUTT(无线冒)
setStrokeJoin(Paint.Join join)
设置线段连接处样式,取值有:Join.MITER(结合处为锐角)、Join.Round(结合处为圆弧)、Join.BEVEL(结合处为直线)
setStrokeMiter(float miter)
设置笔画的倾斜度,90度拿画笔与30拿画笔,画出来的线条样式肯定是不一样的吧。(事实证明,根本看不出来什么区别好吗……囧……)
setPathEffect(PathEffect effect)
设置路径样式;取值类型是所有派生自PathEffect的子类:ComposePathEffect, CornerPathEffect, DashPathEffect, DiscretePathEffect, PathDashPathEffect, SumPathEffect
这四个函数中,setStrokeMiter(float miter)就不再讲了,我做过试验,没什么变化,也就是没啥屌用……,我们分别来看看另外三个函数的具体用法。
2、setStrokeCap(Paint.Cap cap)
设置线帽样式,取值有Cap.ROUND(圆形线帽)、Cap.SQUARE(方形线帽)、Paint.Cap.BUTT(无线帽)我先不讲什么叫做线冒,大家先来看看下面这段代码以及它的效果:
有关自定义View控件的部分就不再讲了,我们已经啰嗦了六篇文章了,如果现在还不知道如何自定义一个控件让其显示绘图效果的话,可以去撞豆腐了
- Paint paint = new Paint();
- paint.setStrokeWidth(80);
- paint.setAntiAlias(true);
- paint.setColor(Color.GREEN);
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeCap(Paint.Cap.BUTT);
- canvas.drawLine(100,200,400,200,paint);
- paint.setStrokeCap(Paint.Cap.SQUARE);
- canvas.drawLine(100,400,400,400,paint);
- paint.setStrokeCap(Paint.Cap.ROUND);
- canvas.drawLine(100,600,400,600,paint);
- //垂直画出x=100这条线
- paint.reset();
- paint.setStrokeWidth(2);
- paint.setColor(Color.RED);
- canvas.drawLine(100,50,100,750,paint);
最后,垂直画出x=100的那条起始线:
从效果图中可以明显看出,从无线冒多出来的那块区域就是线帽!就相当于给原来的直线加上一个帽子一样,所以叫线帽
android的线冒样式是很少的,只有方形和圆形两种,而在Windows SDK中,线冒样式多达十几种。
具体详情见博客:《GDI+学习及代码总结之—–画笔》
3、setStrokeJoin(Paint.Join join)
参数取值有:
- Join.MITER(结合处为锐角)
- Join.Round(结合处为圆弧)
- Join.BEVEL(结合处为直线)
网上说,他们三个的区别如下:
但我运行出来的效果却不是如此,Join.Round和 Join.BEVEL没有明显的区别:
我们画出来三个锐角的path,分别给这三段Path设置不同的连接方式:
- Paint paint = new Paint();
- paint.setStrokeWidth(40);
- paint.setColor(Color.GREEN);
- paint.setStyle(Paint.Style.STROKE);
- paint.setAntiAlias(true);
- Path path = new Path();
- path.moveTo(100,100);
- path.lineTo(450,100);
- path.lineTo(100,300);
- paint.setStrokeJoin(Paint.Join.MITER);
- canvas.drawPath(path,paint);
- path.moveTo(100,400);
- path.lineTo(450,400);
- path.lineTo(100,600);
- paint.setStrokeJoin(Paint.Join.BEVEL);
- canvas.drawPath(path,paint);
- path.moveTo(100,700);
- path.lineTo(450,700);
- path.lineTo(100,900);
- paint.setStrokeJoin(Paint.Join.ROUND);
- canvas.drawPath(path,paint);
4、setPathEffect(PathEffect effect)
设置路径样式;取值类型是所有派生自PathEffect的子类
我们一个个来看他们的效果:
(1)、CornerPathEffect——圆形拐角效果
它的作用就是将原来Path生硬的直线拐角,变成圆形拐角:
上面的那条是Path默认的直线拐角,下面的那条是圆形拐角。
其构造函数为:
- public CornerPathEffect(float radius)
上面这个图,很清晰的展示了利用半径R=50的圆来代替原来两条直线间的夹角。
我们利用代码,再来看看具体效果:
- Paint paint = new Paint();
- paint.setStrokeWidth(4);
- paint.setColor(Color.GREEN);
- paint.setStyle(Paint.Style.STROKE);
- Path path = new Path();
- path.moveTo(100,600);
- path.lineTo(400,100);
- path.lineTo(700,900);
- canvas.drawPath(path,paint);
- paint.setColor(Color.RED);
- paint.setPathEffect(new CornerPathEffect(100));
- canvas.drawPath(path,paint);
- paint.setColor(Color.YELLOW);
- paint.setPathEffect(new CornerPathEffect(200));
- canvas.drawPath(path,paint);
很明显能看出在半径不同情况下,连接位置也是不一样的。
(2)、DashPathEffect——虚线效果
这个功能能够实现虚线段的效果:
它的函数声名如下:
- public DashPathEffect(float intervals[], float phase)
intervals[]: 表示组成虚线的各个线段的长度;整条虚线就是由intervals[]中这些基本线段循环组成的。比如,我们定义new float[] {20,10};那这个虚线段就是由两段线段组成的,第一个可见的线段长为20,每二个线段不可见,长度为10;
对于intervals[]数组的有两个限定:
- 长度必须大于等于2;因为必须有一个实线段和一个空线段来组成虚线。
- 个数必须为偶数,如果是基数,最后一个数字将被忽略;这个很好理解,因为一组虚线的组成必然是一个实线和一个空线成对组成的。
phase: 开始绘制的偏移值
我们来看看代码的运行效果来验证我们想的是否正确:
- Paint paint = getPaint();
- Path path = new Path();
- path.moveTo(100,600);
- path.lineTo(400,100);
- path.lineTo(700,900);
- canvas.drawPath(path,paint);
- paint.setColor(Color.RED);
- //使用DashPathEffect画线段
- paint.setPathEffect(new DashPathEffect(new float[]{20,10,100,100},0));
- canvas.translate(0,100);
- canvas.drawPath(path,paint);
- //画同一条线段,偏移值为15
- paint.setPathEffect(new DashPathEffect(new float[]{20,10,50,100},15));
- paint.setColor(Color.YELLOW);
- canvas.translate(0,100);
- canvas.drawPath(path,paint);
- private Paint getPaint(){
- Paint paint = new Paint();
- paint.setStrokeWidth(4);
- paint.setColor(Color.GREEN);
- paint.setStyle(Paint.Style.STROKE);
- paint.setAntiAlias(true);
- return paint;
- }
从这个效果图中可以看到两点:
第一:红线段的基本组成部分,分别长度为20,10,100,100实线段和空线段组成的
第二:黄线段位移了15,从开始处就可以明显看出效果。原来20的线段,只剩5,所以看起来就像一个点一样。大家也可以发挥想象,利用动画设置偏移量让这条虚线段动起来:
给大家一个提示,使用ValueAnimator,动画长度值设为一个虚线的一个基线的长度,这里的基线是由20,10,100,100组成的,所以一个基线长度是230,然后设置成无限循环,把拿到的值设置为DashPathEffect偏移量即可;
如果看完了我的动画系列,这个小动画是不会成问题的,这里就不再讲了,不懂的同学,看源码吧,源码里有这个动画。
(3)、DiscretePathEffect——离散路径效果
同样,图中第一条线是原生的,第二条线加上离散路径效果后的样式。
DiscretePathEffect就是将原来路径分隔成定长的线段,然后将每条线段随机偏移一段位置,我们可以用它来模拟一种类似生锈铁丝的效果;
它的构造函数如下:
- public DiscretePathEffect(float segmentLength, float deviation)
第二参数deviation:表示被切成的每个小线段的可偏移距离。值越大,就表示每个线段的可偏移距离就越大,就显得越凌乱,值越小,每个线段的可偏移原位置的距离就越小。
我们看下代码效果:
- Paint paint = getPaint();
- Path path = getPath();
- //第一条原生Path
- canvas.drawPath(path,paint);
- //第二条Path
- canvas.translate(0,200);
- paint.setPathEffect(new DiscretePathEffect(2,5));
- canvas.drawPath(path,paint);
- //第三条Path
- canvas.translate(0,200);
- paint.setPathEffect(new DiscretePathEffect(6,5));
- canvas.drawPath(path,paint);
- //第四条Path
- canvas.translate(0,200);
- paint.setPathEffect(new DiscretePathEffect(6,15));
- canvas.drawPath(path,paint);
从第二条和第三条相比,可以明显看出,在仅增大segmentLength的情况下,很明显第三条线段所切的子线段要大一些,所以就没有第二条曲线的那么多线段相交所产生的折点,所以相比第二条更顺滑一些,当然铁锈效果就没有第二条那么明显了。
第三条和第四条相比,在segmentLength都是6的情况下,在第四条仅增大了deviation参数(偏移距离),从效果图中也明显可以看出每个子线段向外偏移的距离也增大了。
从效果图中很明显可以看出各个参数的作用,这里就不多讲了,下面回过头来看看getPath()得到一个随机路径的方法:
- private Path getPath(){
- Path path = new Path();
- // 定义路径的起点
- path.moveTo(0, 0);
- // 定义路径的各个点
- for (int i = 0; i <= 40; i++) {
- path.lineTo(i*35, (float) (Math.random() * 150));
- }
- return path;
- }
(4)、PathDashPathEffect——印章路径效果
这个名字是我自己取的……,因为这个功能就相当于Photoshop中的印章功能。
它的作用就是用另一个路径图案做为印章,沿着指定路径一个个盖上去。
我们先来看看PathDashPathEffect的声明:
- public PathDashPathEffect(Path shape, float advance, float phase,Style style)
- Path shape:表示印章路径,比如我们下面示例中的三角形加右上角一个点;
- float advance:表示两个印章路径间的距离,很容易理解,印章间距离越大,间距就越大。
- float phase:路径绘制偏移距离,与上面DashPathEffect中的float phase参数意义相同
- Style style:表示在遇到转角时,如何操作印章以使转角平滑过渡,取值有:Style.ROTATE,Style.MORPH,Style.TRANSLATE;Style.ROTATE表示通过旋转印章来过渡转角;Style.MORPH表示通过变形印章来过渡转角;Style.TRANSLATE表示通过位移来过渡转角。这三个效果的具体意义,上面会通过具体示例来分别讲解。
如上图所示,印章路径就是一个三角形加右上角一个点。然后就拿这个印章路径在原来的路径上每隔一定距离盖章。
上图的对应代码为:
- Paint paint = getPaint();
- //画出原始路径
- Path path = new Path();
- path.moveTo(100,600);
- path.lineTo(400,100);
- path.lineTo(700,900);
- canvas.drawPath(path,paint);
- //构建印章路径
- Path stampPath = new Path();
- stampPath.moveTo(0,20);
- stampPath.lineTo(10,0);
- stampPath.lineTo(20,20);
- stampPath.close();
- stampPath.addCircle(0,0,3, Path.Direction.CCW);
- //使用印章路径效果
- canvas.translate(0,200);
- paint.setPathEffect(new PathDashPathEffect(stampPath,35,0, PathDashPathEffect.Style.TRANSLATE));
- canvas.drawPath(path,paint);
- //构建印章路径
- Path stampPath = new Path();
- stampPath.moveTo(0,20);
- stampPath.lineTo(10,0);
- stampPath.lineTo(20,20);
- stampPath.close();
- stampPath.addCircle(0,0,3, Path.Direction.CCW);
- //使用印章路径效果
- canvas.translate(0,200);
- paint.setPathEffect(new PathDashPathEffect(stampPath,35,0, PathDashPathEffect.Style.TRANSLATE));
- paint.setPathEffect(new PathDashPathEffect(stampPath,35,0, PathDashPathEffect.Style.TRANSLATE));
- canvas.drawPath(path,paint);
下面我们就来看看,在Style不同的情况下,在转角处都如何处理的:
- private void drawPathDashPathEffect(Canvas canvas){
- Paint paint = getPaint();
- Path path = getPath();
- canvas.drawPath(path,paint);
- canvas.translate(0,200);
- paint.setPathEffect(new PathDashPathEffect(getStampPath(),35,0, PathDashPathEffect.Style.MORPH));
- canvas.drawPath(path,paint);
- canvas.translate(0,200);
- paint.setPathEffect(new PathDashPathEffect(getStampPath(),35,0, PathDashPathEffect.Style.ROTATE));
- canvas.drawPath(path,paint);
- canvas.translate(0,200);
- paint.setPathEffect(new PathDashPathEffect(getStampPath(),35,0, PathDashPathEffect.Style.TRANSLATE));
- canvas.drawPath(path,paint);
- }
- private Path getStampPath(){
- Path path = new Path();
- path.moveTo(0,20);
- path.lineTo(10,0);
- path.lineTo(20,20);
- path.close();
- path.addCircle(0,0,3, Path.Direction.CCW);
- return path;
- }
大家第一眼估计就看得眼花缭乱了,仔细看一下红线处的三角形的样式。
同样是转角,如上图,当Style.MORPH时,就是通过对印章进行变形来过渡转角的
当Style为Style.ROTATE时就是靠旋转印章角度来过渡转角的
当Style为Style.TRANSLATE时,即不会对印章变形也不会对旋转印章角度,而只是通过变改印章的位置来过渡
其中的一个参数float phase,表示路径绘制偏移距离我们还没讲,这个与上面的偏移距离的意义一样,通过改变偏移距离同样可以实现动画
(5)、ComposePathEffect与SumPathEffect
这两个都是用来合并两个特效的。但它们之间是有区别的:
- public ComposePathEffect(PathEffect outerpe, PathEffect innerpe)
- public SumPathEffect(PathEffect first, PathEffect second)
我们来看看效果:
- //画原始路径
- Paint paint = getPaint();
- Path path = getPath();
- canvas.drawPath(path,paint);
- //仅应用圆角特效的路径
- canvas.translate(0,200);
- CornerPathEffect cornerPathEffect = new CornerPathEffect(100);
- paint.setPathEffect(cornerPathEffect);
- canvas.drawPath(path,paint);
- //仅应用虚线特效的路径
- canvas.translate(0,200);
- DashPathEffect dashPathEffect = new DashPathEffect(new float[]{2,5,10,10},0);
- paint.setPathEffect(dashPathEffect);
- canvas.drawPath(path,paint);
- //利用ComposePathEffect先应用圆角特效,再应用虚线特效
- canvas.translate(0,200);
- ComposePathEffect composePathEffect = new ComposePathEffect(dashPathEffect,cornerPathEffect);
- paint.setPathEffect(composePathEffect);
- canvas.drawPath(path,paint);
- //利用SumPathEffect,分别将圆角特效应用于原始路径,然后将生成的两条特效路径合并
- canvas.translate(0,200);
- paint.setStyle(Paint.Style.STROKE);
- SumPathEffect sumPathEffect = new SumPathEffect(cornerPathEffect,dashPathEffect);
- paint.setPathEffect(sumPathEffect);
- canvas.drawPath(path,paint);
特别注意路径D和路径E:
路径D的生成方法为:
- ComposePathEffect(dashPathEffect,cornerPathEffect);
而路径E的生成方法则比较弱智:
- SumPathEffect(cornerPathEffect,dashPathEffect);
好了,到这里,所有的路径效果都讲完了,真TM累死哥了……
二、字体相关
setTextSize(float textSize)设置文字大小
setFakeBoldText(boolean fakeBoldText)
设置是否为粗体文字
setStrikeThruText(boolean strikeThruText)
设置带有删除线效果
setUnderlineText(boolean underlineText)
设置下划线
setTextAlign(Paint.Align align)
设置开始绘图点位置
setTextScaleX(float scaleX)
水平拉伸设置
setTextSkewX(float skewX)
设置字体水平倾斜度,普通斜体字是-0.25,可见往右斜
setTypeface(Typeface typeface)
字体样式
上面的这些方法,我们在 《android Graphics(二):路径及文字》 和 《android Graphics( 五):drawText()详解》 已经详细讲过,这里就不再细讲
下面补充几个没讲到的函数:
1、setLinearText(boolean linearText)
设置是否打开线性文本标识;由于文本想要快速绘制出来,必然是需要提前缓存在显存中的,一般而言每个文字需要一个字节的大小来存储它(当然具体需要多少字节与编码方式有关),那如果是长篇文章,可见所需的大小可想而知。我们可以通过setLinearText (true)告诉Android我们不需要这样的文本缓存。但如果我们不用文本缓存,虽然能够省去一些内存空间,但这是以显示速度为代价的。由于这个是API 1的函数,由于当时的android手机的内存大小还是很小的,所以尽量减少内存使用是每个应用的头等大事,在当时的的环境下这个函数还是很有用的。
但在今天,内存动不动就是4G以上了,文本缓存的所占的那点内存就微不足道了,没有哪个APP会牺牲性能来减少这点这内存占用了,所以这个函数基本没用了。
2、setSubpixelText(boolean subpixelText)
表示是否打开亚像素设置来绘制文本。亚像素的概念比较难理解,首先,我们都知道像素,比如一个android手机的分辨率是1280*720,那就是指它的屏幕在垂直方向有1280个像素点,水平方向上有720个像素点。我们知道每个像素点都是一个独立显示一个颜色的个体。所以如果一副图片,在一个屏幕上用了300*100个相素点,而在另一个屏幕上却用了450*150个像素来显示。那么,请问在哪个屏幕上这张图片显示的更清晰?当然是第二个屏幕,因为它使用的像素点更多,所显示的细节更精细。那么问题来了,android设置在出厂时,设定的像素显示都是固定的几个范围:320*480,480*800,720*1280,1080*1920等等;那么如何在同样的分辨率的显示器中增强显示清晰度呢?
亚像素的概念就油然而生了,亚像素就是把两个相邻的两个像素之间的距离再细分,再插入一些像素,这些通过程序加入的像素就是亚像素。在两个像素间插入的像素个数是通过程序计算出来的,一般是插入两个、三个或四个。
所以打开亚像素显示,是可以在增强文本显示清晰度的,但由于插入亚像素是通过程序计算而来的,所以会耗费一定的计算机性能。注意:亚像素是通过程序计算出来模拟插入的,在没有改变硬件构造的情况下,来改善屏幕分辨率大小。
亚像素显示,是仅在液晶显示器上使用的一种增强字体清晰度的技术。但这种技术有时会出现问题,用投影仪投射到白色墙壁上,会出出字体显示不正常的情况,而且对于老式的CRT显示器是根本不支持的。
在android还没有出现时,windows已经能够支持亚像素显示了,在windows机器中,这个功能叫做ClearType,在以前讲述windows的GDI绘图时,也曾经讲过ClearType的应用效果。
这个图片中的最后一行文字,就是在windows上应用CLearType技术后的显示效果。此图片摘自《 GDI+学习及代码总结之——文本与字体》可见在windows的显示中,还是有明显差别的
但我放在android里面来试,并未发现明显的差别,可能是我的显示器分辨率太高了……汗……
- Paint paint = new Paint();
- paint.setColor(Color.GREEN);
- String text = "乌龟&梦想";
- paint.setTextSize(200);
- paint.setSubpixelText(false);
- canvas.drawText(text,0,200,paint);
- canvas.translate(0,300);
- paint.setSubpixelText(true);
- canvas.drawText(text,0,200,paint);
三、其它
接下来还剩几个跟图片和测量相关的函数,我们接下来分篇慢慢讲解。1、图像处理:
- setShader(Shader shader)
- setShadowLayer(float radius, float dx, float dy, int shadowColor)
- setDither(boolean dither)
- setColorFilter(ColorFilter filter)
- setXfermode(Xfermode xfermode)
- setFilterBitmap(boolean filter)
- clearShadowLayer()
2、measure测量相关
- breakText(char[] text, int index, int count, float maxWidth, float[] measuredWidth)
- measureText(String text)
Paint setStrokeWidth方法:设置空心线宽
setStrokeWidth方法:设置空心线宽
【功能说明】该方法用于设置画笔的空心线宽。该方法在矩形、圆形等图形上有明显的效果。
【基本语法】public void setStrokeWidth (float width)
其中,参数width为线宽,浮点型数据。
【实例演示】下面通过代码来演示如何设置宽线宽的空心画笔。
protected void onDraw(Canvas canvas) { //重载onDraw方法
super.onDraw(canvas);
paint.setColor(Color.RED); //设置画笔颜色
paint.setStyle(Style.STROKE); //设置画笔为空心
paint.setStrokeWidth((float) 10.0); //设置线宽
canvas.drawColor(Color.WHITE);
canvas.drawLine(50, 50, 450, 50, paint); //绘制直线
canvas.drawRect(100, 100, 200, 600, paint); //绘制矩形
canvas.drawRect(300, 100, 400, 600, paint); //绘制矩形
}
在这段代码中,首先设置了画笔的颜色,然后通过setStyle设置画笔为空心,接着通过setStrokeWidth方法设置线宽。最后,用此画笔来绘制直线和矩形。读者运行这段代码,可以在手机屏幕上看到如图显示效果。
设置空心显示效果
设置空心线宽
///慕课网 D3制作图表
https://www.imooc.com/learn/103
*/// 慕课网Canvas绘图详解
https://www.imooc.com/learn/185
*/// 慕课网------程序员的梦工厂
https://www.imooc.com/