现在做的这个项目需要一个折线图的功能,当时想着使用第三方库来实现,结果总不能令我满意,只能通过自定义View用画笔去画了,这才发现 妈的 这东西我不会 赶紧去百度下,后来李大神把他画的折线图给我了,我一看那叫一个顶礼膜拜啊,通过百度和看源码翻译,一个方法一个方法的去看,,总算理出来一丢丢头绪,先记录下吧
在这里边有三个对象非常重要
Paint画笔 Canvas画布 Path路径 不多说了 代码撸起来
1.Paint画笔和Canvas画布
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
/**Paint画笔 Canvas画布
* Created by xuenan on 2016/7/14.
*/
public class MyView1 extends View{
private Paint linePaint;
public MyView1(Context context) {
super(context);
linePaint = new Paint();//初始化画笔
//设置是否抗锯齿;设置抗锯齿会使图像边缘更清晰一些,锯齿痕迹不会那么明显。
linePaint.setAntiAlias(true);
//设置填充样式
//Paint.Style 类型:
//Paint.Style.FILL_AND_STROKE 填充且描边
//Paint.Style.STROKE 描边
//Paint.Style.FILL 填充
linePaint.setStyle(Paint.Style.STROKE);
//设置画笔颜色
linePaint.setColor(Color.GREEN);
//设置画笔宽度
linePaint.setStrokeWidth(8);
//setShadowLayer(float radius, float dx, float dy, int shadowColor) 设置阴影
//radius : 表示阴影的倾斜度
//dx : 水平位移
//dy : 垂直位移
//shadowColor : 阴影颜色
//这个方法不支持硬件加速,所以我们要测试时必须先关闭硬件加速。
//加上setLayerType(LAYER_TYPE_SOFTWARE, null); 并且确保你的最小api8以上。
//linePaint.setShadowLayer(10,15,15,Color.RED);
}
//
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//这两个功能一样,都是用来设置背景颜色的。
canvas.drawColor(Color.parseColor("#F5FFFA"));
//canvas.drawRGB(255, 255, 0);
//1直线绘制
//drawLine(float startX, float startY, float stopX, float stopY,@NonNull Paint paint)
//startX : 开始点X坐标
//startY : 开始点Y坐标
//stopX : 结束点X坐标
//stopY : 结束点Y坐标
//canvas.drawLine(100,100,600,600,linePaint);
//2多条直线
//drawLines(@Size(min=4,multiple=2) float[] pts, int offset, int count, Paint paint)
//drawLines(@Size(min=4,multiple=2) @NonNull float[] pts, @NonNull Paint paint)
//pts : 是点的集合且大小最小为4而且是2的倍数。表示每2个点连接形成一条直线,pts 的组织方式为{x1,y1,x2,y2….}
//offset : 集合中跳过的数值个数,注意不是点的个数!一个点是两个数值
//count : 参与绘制的数值的个数,指pts[]里数值个数,而不是点的个数,因为一个点是两个数值
float [] pts={50,50,200,300,400,450,550,600};
//点(50,50)和点(200,200)连接成一条直线;点(400,400)和点(600,600)连接成直线。
//canvas.drawLines(pts,linePaint);
//表示从第二个50开始连续的4个点(50,200,200,400)连接的直线
//canvas.drawLines(pts,1,4,linePaint);
//3 点即多个点
//drawPoint(float x, float y, @NonNull Paint paint)
//canvas.drawPoint(10,10,linePaint);//一个点
//drawPoints(@Size(multiple=2) @NonNull float[] pts, @NonNull Paint paint)
//drawPoints(@Size(multiple=2) float[] pts, int offset, int count,@NonNull Paint paint)
//canvas.drawPoints(pts,linePaint);//多个点
//4矩形 区别RectF 与Rect ,RectF坐标系是浮点型;Rect坐标系是整形。
//drawRect(@NonNull RectF rect, @NonNull Paint paint)
//drawRect(@NonNull Rect r, @NonNull Paint paint)
//drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)
//left 指定矩形框左上角的x坐标
//top: 指定矩形框左上角的y坐标
//right 指定矩形框右下角的x坐标
//bottom指定矩形框右下角的y坐标
//canvas.drawRect(new Rect(20,20,300,200),linePaint);
//canvas.drawRect(new RectF(20,20,300,200),linePaint);
//canvas.drawRect(20,20,300,200,linePaint);
//5圆角矩形
//RectF: 绘制的矩形
//rx : 生成圆角的椭圆X轴半径
//ry : 生成圆角的椭圆Y轴的半径
//drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint)
//drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,@NonNull Paint paint)
//if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//这个方法有点坑啊 只能在5.0以上使用,推荐使用下边的方法代替
// canvas.drawRoundRect(200,200,1000,800,15,15,linePaint);
//}
//canvas.drawRoundRect(new RectF(200,200,1000,800),15,15,linePaint);
//6圆形
//drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
//cx : 圆心X坐标
//cy : 圆心Y坐标
//radius : 半径
//canvas.drawCircle(900,900,500,linePaint);
//7椭圆 参数为椭圆的矩形边界
//drawOval(@NonNull RectF oval, @NonNull Paint paint)
//drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)
//canvas.drawOval(new RectF(200,200,1000,800),linePaint);
//if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// canvas.drawOval(200,200,1000,800,linePaint);
//}
//8 圆弧
//oval : 生成椭圆的矩形
//startAngle : 弧开始的角度 (X轴正方向为0度,顺时针弧度增大)
//sweepAngle : 绘制多少弧度 (注意不是结束弧度)
//useCenter : 是否有弧的两边 true有两边 false无两边
//drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,@NonNull Paint paint)
//drawArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean useCenter, @NonNull Paint paint)
//if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// canvas.drawArc(100,100,800,600,0,90,true,linePaint);
//}
//canvas.drawArc(new RectF(100,100,800,600),0,90,true,linePaint);
}
}
- 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
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
2.Path路径 为了直观 我加上了网格
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.WindowManager;
/**Paint画笔 Canvas画布 Path 路径
* Created by xuenan on 2016/7/14.
*/
/**Path的方法
*moveTo 移动起点 移动下一次操作的起点位置
*lineTo 连接直线 连接上一个点到当前点之间的直线
*setLastPoint 设置终点 重置最后一个点的位置
*close 闭合路劲 从最后一个点连接最初的一个点,形成一个闭合区域
*addRect 添加矩形 添加矩形到当前Path
*addRoundRect 添加圆角矩形 添加圆角矩形到当前Path
*addOval 添加椭圆 添加椭圆到当前Path
*addCircle 添加圆 添加圆到当前Path
*addPah 添加路劲 添加路劲到当前Path
*addArc 添加圆弧 添加圆弧到当前Path
*arcTo 圆弧 绘制圆弧,注意和addArc的区别
*isEmpty 是否为空 判定Path是否为空
*isRect 是否为矩形 判定Path是否是一个矩形
*set 替换路劲 用新的路劲替换当前路劲的所有内容
*offset 偏移路劲 对当前的路劲进行偏移
*quadTo 贝塞尔曲线 二次贝塞尔曲线的方法
*cubicTo 贝塞尔曲线 三次贝塞尔曲线的方法
*rMoveTo,rlineTo,rQuadTo,rCubicTo rXxx方法 不带r的方法是基于原点坐标系(偏移量),带r的基于当前点坐标系(偏移量)
*op 布尔操作 对两个Path进行布尔运算(交集,并集)等操作
*setFillType 填充模式 设置Path的填充模式
*getFillType 填充模式 获取Path的填充
*isInverseFillType 是否逆填充 判断是否是逆填充模式
*toggleInverseFillType 相反模式 切换相反的填充模式
*getFillType 填充模式 获取Path的填充
*incReserve 提示方法 提示Path还有多少个点等待加入
*computeBounds 计算边界 计算Path的路劲
*reset,rewind 重置路劲 清除Path中的内容(reset相当于new Path , rewind 会保留Path的数据结构)
*transform 矩阵操作 矩阵变换
*/
public class MyView2 extends View{
private Paint path_paint;//路径绘制
private Paint paint; //网格绘图
private Context mcontext;
private int width2,height2;
public MyView2(Context context) {
super(context);
this.mcontext =context;
WindowManager manager = (WindowManager) mcontext.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(outMetrics);
width2 = outMetrics.widthPixels;
height2 = outMetrics.heightPixels;
path_paint = new Paint();
path_paint.setAntiAlias(true);
path_paint.setStyle(Paint.Style.FILL_AND_STROKE);
path_paint.setStrokeWidth(10);
path_paint.setColor(Color.parseColor("#FF0000"));
//paint.setStyle(Paint.Style.FILL);,设置画笔为实心。一些线条将在画布上看不见。
paint = new Paint();
paint.setColor(Color.parseColor("#A8A8A8"));
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(1);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#F5FFFA"));//画布的背景
//网格线的绘制
final int width = width2;
final int height = height2;
final int space = 100; //长宽间隔
int vertz = 0;
int hortz = 0;
for(int i=0;i<100;i++){
canvas.drawLine(0, vertz, width, vertz, paint);
canvas.drawLine(hortz, 0, hortz, height, paint);
vertz+=space;
hortz+=space;
}
Path path = new Path();
//1.lineTo 连接直线 连接上一个点到当前点之间的直线
//path.lineTo(200,200);
//path.lineTo(400, 0);
//2.方法名 作用 是否影响之前的操作 是否影响之后的操作
//moveTo 移动下一次操作的起点位置 否 是
//setLastPoint 改变上一次操作点的位置 是 是
//当我们绘制线条之前,调用moveTo 和 setLastPoint效果是一样的,
//都是对坐标原点(0,0)进行操作。setLastPoint是重置上一次操作的最后一点
//path.lineTo(200, 200);
//path.moveTo(300,300);
//path.lineTo(400, 0);
//path.lineTo(200, 200);
//path.setLastPoint(300,100);
//path.lineTo(400, 0);
//3.close方法连接最后一个点和最初一个点(如果两个点不重合)形成一个闭合的图形。
//close的作用的封闭路径,如果连接最后一个点和最初一个点任然无法形成闭合的区域,那么close什么也不做。
//path.moveTo(100,100);
//path.lineTo(500,100);
//path.lineTo(300,400);
//path.close();
//4.二次贝塞尔曲线
//public void quadTo(float x1, float y1, float x2, float y2)
//path.moveTo(100, 400);
//path.quadTo(300, 100, 400, 400);
//5.三次贝塞尔曲线
//public void cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
//cubicTo方法比quadTo方法多了一个点坐标,那么其中(x1,y1) 为控制点,(x2,y2)为控制点,(x3,y3) 为结束点。
//path.moveTo(100, 400);
//path.cubicTo(100, 400, 300, 100, 400, 400);
//6.1Path中添加基本图形以及区分addArc和arcTo
//圆形
//addCircle(float x, float y, float radius, Path.Direction dir)
//椭圆
//addOval(RectF oval, Path.Direction dir)
//addOval(float left, float top, float right, float bottom, Path.Direction dir)
//矩形
//addRect(RectF rect, Path.Direction dir)
//addRect(float left, float top, float right, float bottom, Path.Direction dir)
//圆角矩形
//addRoundRect(RectF rect, float rx, float ry, Path.Direction dir)
//addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Path.Direction dir)
//addRoundRect(RectF rect, float[] radii, Path.Direction dir)
//addRoundRect(float left, float top, float right, float bottom, float[] radii, Path.Direction dir)
//Direction的意思是方向,指导,趋势。点进去跟一下你会发现Direction是一个枚举类型(Enum)
// 分别有CW(顺时针),CCW(逆时针)两个常量。那么它的作用主要有以下两点:
//1:在添加图形时确定闭合顺序(各个点的记录顺序)
//:对自相交图形的渲染结果有影响
//闭合的问题,相交问题与设置填充模式有关。
//path.addRect(100, 200, 500, 400, Path.Direction.CCW);
//path.setLastPoint(400,300);
//path.addCircle(300,300,200, Path.Direction.CW);
//6.2addPath路径合并
//addPath方法就是将两个路径合并到一起。
//第二个方法的dx,dy指的是偏移量,第三个方法是添加到当前path之前先使用Matrix进行变换
//public void addPath(Path src)
//public void addPath(Path src, float dx, float dy)
//public void addPath(Path src, Matrix matrix)
//path.addRect(100,100,400,300, Path.Direction.CW);
//Path src=new Path();
//src.addCircle(300,300,100, Path.Direction.CW);
//path.addPath(src,0,100);
//6.3addArc与arcTo
//addArc(RectF oval, float startAngle, float sweepAngle)
//addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle)
//arcTo(RectF oval, float startAngle, float sweepAngle)
//arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
//arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo)
//区别
//名称 作用 区别
//addArc 添加一个圆弧到Path 直接添加一个圆弧到path中,和上一次操作点无关
//arcTo 添加一个圆弧到Path 添加一个圆弧到path中,如果圆弧的起点和上次操作点坐标不同就连接两个点
//startAngle表示开始圆弧度数(0度与X轴方向对齐,顺时针移动,弧度增大)。
//注意:sweepAngle表示运动了多少弧度,并不是结束弧度。
//forceMoveTo表示“是否强制使用moveTo”,也就是说是否使用moveTo将上一次操作点移动到圆弧的起点坐标。
// 默认是false。
//true 将最后一个点移动到圆弧起点,即不连接最后一个点与圆弧起点
//false 不移动,而是连接最后一个点与圆弧起点(注意之前没有操作的话,不会连接原点)
//path.lineTo(200, 200);
//RectF rectF = new RectF(100, 100, 400, 400);
//path.arcTo(rectF, 0, 270, true);
// path.addArc(rectF,0,270);和上面一句等价
//path.arcTo(rectF, 0, 270, false);
//6.4 isEmpty、 isRect、 set 和 offset
//6.4.1 isEmpty判断path中是否包含内容。path.isEmpty()
//Log.e("-----", "----" + path.isEmpty());//-----: ----true
//path.lineTo(100,100);
//Log.e("-----","----"+path.isEmpty());//-----: ----false
//6.4.2 isRect 判断path是否是一个矩形,如果是一个矩形的话,
// 会将矩形的信息存放进参数rect中。isRect(RectF rect)
//RectF rectF = new RectF();
//rectF.left = 100;
//rectF.top = 100;
//rectF.right = 400;
//rectF.bottom = 300;
//path.addRect(rectF, Path.Direction.CW);
//boolean isRect = path.isRect(rectF);
//Log.e("-----", "------" + isRect);//-----: ------true
//6.4.3 set public void set(Path src)将新的path赋值到现有path。
// 相当于运算符中的“=”,如a=b,把b赋值给a
//path.addRect(100,100,400,300, Path.Direction.CW);
//Path src=new Path();
//src.addCircle(300,200,100, Path.Direction.CW);
//path.set(src);
//6.4.4 offset平移
//public void offset(float dx, float dy)
//public void offset(float dx, float dy, Path dst)
//这个方法就是对Path进行一段平移,正方向和X轴,Y轴方向一致(如果dx为正数则向右平移,
//反之向左平移;如果dy为正则向下平移,反之向上平移)。我们看到第二个方法多了一个dst,
//这个又是一个什么玩意呢,其实参数das是存储平移后的path的。
//先看两个参数的
//path.addCircle(300, 200, 100, Path.Direction.CW);
//path.offset(-100, 100);
//再看三个参数的
//从运行效果图可以看出,虽然我们在dst中添加了一个圆形,但是并没有表现出来,
//所以,当dst中存在内容时,dst中原有的内容会被清空,而存放平移后的path。
//也就是说dst=path;即dst.set(path)哎 然并卵的东西
//path.addCircle(300, 200, 100, Path.Direction.CW);
//Path dst = new Path();
//dst.addCircle(500, 200, 200, Path.Direction.CW);
//path.offset(-100, 100, dst);
//7 FillType 对两个参数取交集 并集 补集
//public void setFillType(Path.FillType ft)
//public Path.FillType getFillType()
//setFillType方法中的参数Path.FillType为枚举类型:
//FillType.WINDING 取path所有所在区域 默认值
//FillType.EVEN_ODD 取path所在并不相交区域
//FillType.INVERSE_WINDING 取path所有未占区域
//FillType.INVERSE_EVEN_ODD 取path未占或相交区域
//7.1 WINDING 并集
//path.addCircle(300,200,100, Path.Direction.CW);
//path.addCircle(200,200,100, Path.Direction.CW);
//path.setFillType(Path.FillType.WINDING);
//7.2 EVEN_ODD
//path.addCircle(300,200,100, Path.Direction.CW);
//path.addCircle(200,200,100, Path.Direction.CW);
//path.setFillType(Path.FillType.EVEN_ODD);
//7.3 INVERSE_WINDING 补集
//path.addCircle(300,200,100, Path.Direction.CW);
//path.addCircle(200,200,100, Path.Direction.CW);
//path.setFillType(Path.FillType.INVERSE_WINDING);
//7.4 INVERSE_EVEN_ODD 并集
path.addCircle(300,200,100, Path.Direction.CW);
path.addCircle(200,200,100, Path.Direction.CW);
path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
path.toggleInverseFillType();
canvas.drawPath(path, path_paint);
}
}
- 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
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
3.文字设计
package com.longlian.paintdemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.WindowManager;
/**文字绘制
* Created by xuenan on 2016/7/15.
*/
/**
*text_paint.setAntiAlias(true); //指定是否使用抗锯齿功能 如果使用会使绘图速度变慢 默认false
*text_paint.setStyle(Paint.Style.FILL);//绘图样式 对于设文字和几何图形都有效
*text_paint.setTextAlign(Paint.Align.LEFT);//设置文字对齐方式 取值:align.CENTER、align.LEFT或align.RIGHT 默认align.LEFT
*text_paint.setTextSize(12);
*text_paint.setStrokeWidth(5);//设置画笔宽度
*text_paint.setTextSize(80);//设置文字大小
*样式设置
*text_paint.setFakeBoldText(true);//设置是否为粗体文字
*text_paint.setUnderlineText(true);//设置下划线
*text_paint.setTextSkewX((float) -0.25);//设置字体水平倾斜度 普通斜体字是-0.25
*text_paint.setStrikeThruText(true);//设置带有删除线效果
*其它设置
*text_paint.setTextScaleX(2);//只会将水平方向拉伸 高度不会变
*
**/
public class MyView3 extends View{
private Paint text_paint;
private Paint paint; //网格绘图
private Context mcontext;
private int width2,height2;
public MyView3(Context context) {
super(context);
this.mcontext =context;
WindowManager manager = (WindowManager) mcontext.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(outMetrics);
width2 = outMetrics.widthPixels;
height2 = outMetrics.heightPixels;
text_paint = new Paint();
text_paint.setStrokeWidth(3);
text_paint.setTextSize(50);
text_paint.setColor(Color.RED);
paint = new Paint();
paint.setColor(Color.parseColor("#A8A8A8"));
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(1);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.parseColor("#F5FFFA"));//画布的背景
//网格线的绘制
final int width = width2;
final int height = height2;
final int space = 100; //长宽间隔
int vertz = 0;
int hortz = 0;
for(int i=0;i<100;i++){
canvas.drawLine(0, vertz, width, vertz, paint);
canvas.drawLine(hortz, 0, hortz, height, paint);
vertz+=space;
hortz+=space;
}
//1、文本绘图样式
//设置绘图样式 为填充
//text_paint.setStyle(Paint.Style.FILL);
//canvas.drawText("我是一颗小小的石头", 100, 100, text_paint);
//设置绘图样式 为描边
//text_paint.setStyle(Paint.Style.STROKE);
//canvas.drawText("我是一颗小小的石头", 100, 300, text_paint);
//设置绘图样式 为填充且描边
//text_paint.setStyle(Paint.Style.FILL_AND_STROKE);
//canvas.drawText("我是一颗小小的石头", 100,500, text_paint);
//2、setTextAlign(Paint.Align align) 文字的对齐方式
//text_paint.setStyle(Paint.Style.FILL);
//设置对齐方式 左对齐
//text_paint.setTextAlign(Paint.Align.LEFT);
//canvas.drawText("小小的石头", 500,100, text_paint);//点(500,100)在文本的左边
//设置对齐方式 中间对齐
//text_paint.setTextAlign(Paint.Align.CENTER);
//canvas.drawText("小小的石头", 500, 200, text_paint);//点(500,100)在文本的中间
//设置对齐方式 右对齐
//text_paint.setTextAlign(Paint.Align.RIGHT);
//canvas.drawText("小小的石头", 500,300, text_paint);//点(500,100)在文本的右边
//3、文字样式设置
//text_paint.setStyle(Paint.Style.FILL);
//text_paint.setFakeBoldText(true);//是否粗体文字
//text_paint.setUnderlineText(true);//设置下划线
//text_paint.setStrikeThruText(true);//设置删除线效果
//canvas.drawText("小小的石头", 200, 200, text_paint);
//4、文字倾斜度设置
//可见普通斜体字是-0.25f,大于-0.25f 向左倾斜,小于 -0.25f 向右倾斜。
//text_paint.setStyle(Paint.Style.FILL);
//text_paint.setTextSkewX(-0.25f);
//canvas.drawText("小小的石头", 100, 100, text_paint);
//text_paint.setTextSkewX(0.25f);
//canvas.drawText("小小的石头", 100, 200, text_paint);
//text_paint.setTextSkewX(-0.5f);
//canvas.drawText("小小的石头", 100, 300, text_paint);
//5、水平拉伸设置 仅是水平方向拉伸,高度并未改变。
//text_paint.setStyle(Paint.Style.FILL);
//text_paint.setTextScaleX(1);//不拉伸
//canvas.drawText("小小的石头", 100, 100, text_paint);
//text_paint.setTextScaleX(2);//水平方向拉伸2倍
//canvas.drawText("小小的石头", 100, 200, text_paint);
//text_paint.setTextScaleX(3);//水平方向拉伸3倍
//canvas.drawText("小小的石头", 100, 300, text_paint);
//6.canvas绘制文字
//6.1、drawText
//drawText(String text, float x, float y, Paint paint)
//drawText(char[] text, int index, int count, float x, float y, Paint paint)
//drawText(CharSequence text, int start, int end, float x, float y, Paint paint)
//下边两个方法要求sdk>=23
//drawTextRun(char[] text, int index, int count, int contextIndex,
//int contextCount, float x, float y, boolean isRtl, Paint paint)
//drawTextRun(CharSequence text, int start, int end, int contextStart,
//int contextEnd, float x, float y, boolean isRtl, Paint paint)
//第一个构造函数 : 是最普通的。
//第二个构造函数 : text 字节数组;index 表示第一个要绘制的文字索引;count 需要绘制的文字个数。
//第三个构造函数 : text 表示字符 (注意与上面比较);start 开始截取字符的索引号;
//end 结束截取字符的索引号。(注意和上面的区别) [start , end ) 包含 start 但不包含 end
//第四个构造函数和第五个构造函数 : contextIndex 和 index 相同 ;
//contextCount 大于等于 count ; isRtl 表示排列顺序,
//true 表示正序,false 表示倒序(这里的倒是指第一个字符变到最后一个字符,
//最后一个字符变到第一个字符)。 注意了drawTextRun方法是在 skd23 才引入的方法。
//text_paint.setStyle(Paint.Style.FILL);
//canvas.drawText("我是一颗小小的石头".toCharArray(), 1, 4, 100, 100, text_paint);
//canvas.drawText("我是一颗小小的石头", 1, 4, 100, 200, text_paint);
//最小sdk23
//if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//倒序
// canvas.drawTextRun("我是一颗小小的石头".toCharArray(), 1, 4, 1, 4, 100, 400, false, text_paint);
//正序
// canvas.drawTextRun("我是一颗小小的石头".toCharArray(), 1, 4, 1, 4, 100, 300, true, text_paint);
// }
//6.2、drawPosText
//drawPosText(String text, float[] pos, Paint paint)
//drawPosText(char[] text, int index, int count, float[] pos, Paint paint)
//float[] pos = {100, 100, 200, 200, 300, 300, 400, 400, 500, 500, 600, 600};
//canvas.drawPosText("我是一颗小小", pos, text_paint);
//6.3、drawTextOnPath
//drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint)
//drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, float vOffset, Paint paint)
//index,count : 和上面截取参数含义一样,这里不再累诉。
//hOffset : 与路径起点的水平偏移量 ,正数向 X 轴正方向移动(右移);负数向 X 轴负方向移动(左移)
//如果是圆弧:正数是顺时针的偏移量;反之是逆时针的偏移量
//vOffset : 与路径中心的垂直偏移量,正数向 Y 轴正方向移动(下移);负数向Y 轴负方向移动(上移)
//如果是圆弧正数向 Y 轴负方向移动(上移);负数向Y 轴正方向移动(下移)
//Path mPath = new Path();
//Paint mpaint = new Paint();
//mpaint.setStrokeWidth(5);
//mpaint.setTextSize(80);
//mpaint.setColor(Color.GREEN);
//mpaint.setStyle(Paint.Style.STROKE);
//6.3.1
//mPath.moveTo(100, 100);
//mPath.lineTo(800, 100);
//canvas.drawPath(mPath, mpaint);
//canvas.drawTextOnPath("我是一颗小小的石头", mPath,10, 100, text_paint);
//6.3.2
//mPath.addCircle(500, 500, 200, Path.Direction.CW);
//canvas.drawPath(mPath, mpaint);
//canvas.drawTextOnPath("我是一颗小小的石头", mPath, 40,20, text_paint);
//6.4、Typeface(字体样式设置)
//setTypeface(Typeface typeface)
//参数类型是枚举类型,枚举值如下:
//Typeface.NORMAL //正常体
//Typeface.BOLD //粗体
//Typeface.ITALIC //斜体
//Typeface.BOLD_ITALIC //粗斜体
//Typeface是用来设置字体样式的,通过paint.setTypeface()来指定。
//可以指定系统中的字体样式,也可以指定自定义的样式文件中获取。
//要构建Typeface时,可以指定所用样式的正常体、斜体、粗体等,如果指定样式中,
//没有相关文字的样式就会用系统默认的样式来显示,一般默认是宋体。
//Typeface typeface;
//typeface = Typeface.create("宋体", Typeface.NORMAL);
//text_paint.setTypeface(typeface);
//canvas.drawText("我是一颗小小的石头", 100, 100, text_paint);
//设置楷体根本没起作用,在系统的字体当中没有找到楷体。
//typeface = Typeface.create("楷体", Typeface.NORMAL);
//mPaint.setTypeface(typeface);
//canvas.drawText("我是一颗小小的石头", 100, 200, mPaint);
//----------------------------------------------------------
//自定义字体
//createFromAsset(AssetManager mgr, String path) //Asset中获取
//createFromFile(File path) //文件路径获取
//createFromFile(String path) //外部路径获取
//首先在main下创建assets文件夹,然后在assets文件夹创建fonts文件夹,
//最后在fonts文件夹下放入font1.ttf
Typeface typeface;
typeface = Typeface.createFromAsset(mcontext.getAssets(), "fonts/font1.ttf");
//Typeface.createFromFile(mContext.getFilesDir()+"/font1.ttf")
text_paint.setTypeface(typeface);
canvas.drawText("我是一颗小小的石头", 100, 100, text_paint);
typeface = Typeface.createFromAsset(mcontext.getAssets(), "fonts/font2.ttf");
text_paint.setTypeface(typeface);
canvas.drawText("我是一颗小小的石头", 100, 200, text_paint);
}
}