参考:
- https://blog.csdn.net/harvic880925/article/details/51010839
基本用法
基本设置函数
- 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 :仅描边
- setStrokeWidth(float width) 设置画笔宽度
- setAntiAlias(boolean aa) 设置画笔是否抗锯齿
以上函数,我们基本上都用过了;
其他设置函数
- setStrokeCap(Paint.Cap cap) 设置线冒样式,取值有:
- Cap.ROUND(圆形线冒);
- Cap.SQUARE(方形线冒)
- Cap.BUTT(无线冒)
- setStrokeJoin(Paint.Join join) 设置线段连接处样式,取值有:
- Join.MITER(结合处为锐角);
- Join.Round(结合处为圆弧);
- Join.BEVEL(结合处为直线)
- setStrokeMiter(float miter) 设置笔画的倾斜度
- setPathEffect(PathEffect effect) 设置路径样式;取值类型是所有PathEffect的子类:
- ComposePathEffect;
- CornerPathEffect;
- DashPathEffect;
- DiscretePathEffect,
- PathDashPathEffect,
- SumPathEffect
setStrokeCap
设置线帽样式,什么叫做线帽,看下面图示:
val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
strokeWidth = 80f
color = Color.GREEN
style = Paint.Style.STROKE
}
paint.strokeCap = Paint.Cap.BUTT // 无线帽
canvas.drawLine(100f, 200f, 400f, 200f, paint)
paint.strokeCap = Paint.Cap.SQUARE // 方形
canvas.drawLine(100f, 400f, 400f, 400f, paint)
paint.strokeCap = Paint.Cap.ROUND // 圆形
canvas.drawLine(100f, 600f, 400f, 600f, paint)
paint.strokeWidth = 2f
paint.color = Color.RED
canvas.drawLine(100f, 0f, 100f, height.toFloat(), paint)
从无线冒多出来的那块区域就是线帽!就相当于给原来的直线加上一个帽子一样,所以叫线帽;
Android 目前只有3种线帽子;
setStrokeJoin(Paint.Join join)
设置线段连接处样式;
val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
strokeWidth = 40f
color = Color.GREEN
style = Paint.Style.STROKE
}
Path().let {
it.moveTo(100f, 100f)
it.lineTo(200f, 100f)
it.lineTo(100f, 200f)
paint.strokeJoin = Paint.Join.MITER // 锐角
canvas.drawPath(it, paint)
it.moveTo(100f, 300f)
it.lineTo(200f, 300f)
it.lineTo(100f, 400f)
paint.strokeJoin = Paint.Join.BEVEL // 结合处为直线
canvas.drawPath(it, paint)
it.moveTo(100f, 500f)
it.lineTo(200f, 500f)
it.lineTo(100f, 600f)
paint.strokeJoin = Paint.Join.ROUND // 结合处为圆弧
canvas.drawPath(it, paint)
}
从图上看,BEVEL
与ROUND
并没有明显区别;
setPathEffect
设置路径样式;取值类型是所有派生自PathEffect的子类;
1. CornerPathEffect-圆形拐角效果
将原来Path生硬的直线拐角,变成圆形拐角,从下图示
CornerPathEffect构造:
// radius 当前连接两条直线所使用的圆的半径
public CornerPathEffect(float radius)
上图为利用半径R=50的圆来代替原来两条直线间的夹角;
示例代码:
val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
strokeWidth = 2f
color = Color.GREEN
style = Paint.Style.STROKE
}
Path().let {
it.moveTo(100f,600f)
it.lineTo(400f,100f)
it.lineTo(700f,900f)
canvas.drawPath(it, paint)
paint.pathEffect = CornerPathEffect(100f) // radius = 100f
canvas.drawPath(it, paint.apply { color = Color.BLACK })
paint.pathEffect = CornerPathEffect(200f)
canvas.drawPath(it, paint.apply { color = Color.RED })
}
2. DashPathEffect——虚线效果
功能能够实现虚线段的效果,如下图:
DashPathEffect构造
public DashPathEffect(float intervals[], float phase)
参数:
- intervals[]:表示组成虚线的各个线段的长度;整条虚线就是由intervals[]中这些基本线段循环组成的。比如,我们定义new float[] {20,10};那这个虚线段就是由两段线段组成的,第一个可见的线段长为20,每二个线段不可见,长度为10;
-
phase:开始绘制的偏移值
intervals 的 长度必须大于等于2;必须有一个实线段和一个空线段来组成虚线,个数必须为偶数,如果是基数,最后一个数字将被忽略;
Path().let {
it.moveTo(100f, 600f)
it.lineTo(400f, 100f)
it.lineTo(700f, 900f)
canvas.drawPath(it, paint)
// 第一条实线长度为20,第二个空线长度为10,第三个实线长为100,第四条空线长充为100
paint.pathEffect = DashPathEffect(floatArrayOf(20f, 10f, 100f, 100f), 0f)
canvas.translate(0f, 100f)
canvas.drawPath(it, paint.apply { color = Color.BLACK })
// 设置偏移值
paint.pathEffect = DashPathEffect(floatArrayOf(20f, 10f, 50f, 100f), 15f)
canvas.translate(0f, 100f)
canvas.drawPath(it, paint.apply { color = Color.RED })
}
注意上面蓝色箭头,因为第二条,开始偏移了15f,所以开始是5了,明显缩短了;
让线动起来(不断改变 偏离量 phase
);
// 20f, 10f, 100f, 100f 和为 230
val valueAnim1 = ValueAnimator.ofFloat(0f, 230f).apply {
duration = 1000
repeatMode = ValueAnimator.RESTART
repeatCount = ValueAnimator.INFINITE
interpolator = LinearInterpolator()
addUpdateListener {
path1Phase = it.animatedValue as Float
postInvalidate()
}
}
// 区间为(15, -165), 15 + 165 = 180
val valueAnim2 = ValueAnimator.ofFloat(15f, -165f).apply {
duration = 2000
repeatMode = ValueAnimator.RESTART
repeatCount = ValueAnimator.INFINITE
interpolator = LinearInterpolator()
addUpdateListener {
e("size: ${path2Phase}")
path2Phase = it.animatedValue as Float
postInvalidate()
}
}
// 联合动画
AnimatorSet().apply {
play(valueAnim1).with(valueAnim2)
}.start()
3.DiscretePathEffect——离散路径效果
如下图,图中第一条线是原生的,第二条线加上离散路径效果后的样式;
DiscretePathEffect就是将原来路径分隔成定长的线段,然后将每条线段随机偏移一段位置; Discrete 离散的;
DiscretePathEffect构造:
public DiscretePathEffect(float segmentLength, float deviation)
参数说明:
- segmentLength:表示将原来的路径切成多长的线段。如果值为2,那么这个路径就会被切成一段段由长度为2的小线段。所以这个值越小,所切成的小线段越多;这个值越大,所切成的小线段越少。
- deviation:表示被切成的每个小线段的可偏移距离。值越大,就表示每个线段的可偏移距离就越大,就显得越凌乱,值越小,每个线段的可偏移原位置的距离就越小。
示例代码:
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
strokeWidth = 2f
color = Color.GREEN
style = Paint.Style.STROKE
}
val path = getPath()
// 原始
canvas.drawPath(path,paint)
canvas.translate(0f, 200f)
paint.pathEffect = DiscretePathEffect(2f, 5f)
canvas.drawPath(path,paint)
canvas.translate(0f, 200f)
paint.pathEffect = DiscretePathEffect(6f, 5f)
canvas.drawPath(path,paint)
canvas.translate(0f, 200f)
paint.pathEffect = DiscretePathEffect(6f, 15f)
canvas.drawPath(path,paint)
}
private fun getPath(): Path {
return Path().apply {
moveTo(0f, 0f)
for (i in 0..40) {
lineTo(i * 35f, (Math.random() * 150).toFloat())
}
}
}
4. PathDashPathEffect——印章路径效果
用另一个路径图案做为印章,沿着指定路径一个个盖上去;
构造函数:
public PathDashPathEffect(Path shape, float advance, float phase,Style style)
参数说明:
- Path shape:表示印章路径;
- float advance:表示两个印章路径间的距离,间隙;
- float phase:路径绘制偏移距离,与DashPathEffect中的phase参数意义相同;
- Style style:表示在遇到转角时,如何操作印章以使转角平滑过渡,取值有:
- Style.ROTATE: 表示通过旋转印章来过渡转角
- Style.MORPH: 表示通过变形印章来过渡转角
- Style.TRANSLATE: 表示通过位移来过渡转角
示例代码:
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
strokeWidth = 2f
color = Color.GREEN
style = Paint.Style.STROKE
}
val path = getPath()
canvas.drawPath(path, paint)
canvas.translate(0f, 200f)
paint.pathEffect = PathDashPathEffect(getDashPath(), 30f, 0f, PathDashPathEffect.Style.MORPH)
canvas.drawPath(path, paint.apply { color = Color.RED })
canvas.translate(0f, 200f)
paint.pathEffect = PathDashPathEffect(getDashPath(), 30f, 0f, PathDashPathEffect.Style.TRANSLATE)
canvas.drawPath(path, paint.apply { color = Color.RED })
canvas.translate(0f, 200f)
paint.pathEffect = PathDashPathEffect(getDashPath(), 30f, 0f, PathDashPathEffect.Style.ROTATE)
canvas.drawPath(path, paint.apply { color = Color.RED })
}
// 三角形
private fun getDashPath(): Path {
return Path().apply {
moveTo(10f, 10f)
lineTo(20f, 10f)
lineTo(15f, 20f)
close()
}
}
注意转弯处,的变型
5. ComposePathEffect与SumPathEffect
用来合并两个特效的,但有区别;
// 有先后顺序的,将第二个参数的innerpe的特效作用于路径上
// 然后再在此加了特效的路径上,再加第一个参数dashEffect特效。
public ComposePathEffect(PathEffect outerpe, PathEffect innerpe)
// 对原始路径分别作用第一个特效和第二个特效。然后再将这两条路径合并,做为最终结果。
public SumPathEffect(PathEffect first, PathEffect second)
示例代码:
// 原始
val path = getPath()
canvas.drawPath(path, paint)
// 圆角特效
canvas.translate(0f, 150f)
val cornerEffect = CornerPathEffect(100f)
paint.pathEffect = cornerEffect
canvas.drawPath(path, paint.apply { color = Color.RED })
// 虚线特效
canvas.translate(0f, 150f)
val dashEffect = DashPathEffect(floatArrayOf(2f, 5f, 10f, 10f), 0f)
paint.pathEffect = dashEffect
canvas.drawPath(path, paint.apply { color = Color.RED })
// 利用ComposePathEffect先应用圆角特效,再应用虚线特效
canvas.translate(0f, 150f)
paint.pathEffect = ComposePathEffect(dashEffect, cornerEffect) //位置交换就只有dashEffect效果
canvas.drawPath(path, paint)
// 利用SumPathEffect,分别将圆角特效应用于原始路径,然后将生成的两条特效路径合并
canvas.translate(0f, 150f)
paint.pathEffect = SumPathEffect(cornerEffect, dashEffect)
canvas.drawPath(path, paint)
说明:
特别注意路径D和路径E:
路径D的生成方法为:
ComposePathEffect(dashEffect, cornerEffect) //位置交换就只有dashEffect效果
表示先将圆角特效应用于原始路径,得到路径B,然后再在路径B的基础上应用虚线特效得到最终的效果D;
尝试交换参数位置时,居然只有dashEffect
效果了;
路径E的生成方法为:
SumPathEffect(cornerEffect, dashEffect) // 参数位置可交换
先将圆角特效应用于原始路径A得到路径B,然后将虚线特效应依然应用于原始路径,得到路径C. 然后将路径B和路径C合并(即画在一起),就得到路径E ;
文字设置相关函数
常用文字设置相关函数
- 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)
之前都有接触过;