转载请以链接形式标明出处: 本文出自:103style的博客
设置画笔的线冒样式:
注意: Paint.Cap.ROUND、Paint.Cap.SQUARE 会在线长度的基础上首尾添加一个通过 setStrokeWidth 设置的宽度。
示例如下:依次为 无设置、Paint.Cap.BUTT、Paint.Cap.SQUARE、Paint.Cap.ROUND。 可以看到 ROUND 和 SQUARE 样式的明显长一点。
public StrokeJoinCapView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
paint.setStrokeWidth(60);
paint.setStyle(Paint.Style.STROKE);
paint.setDither(true);
paint.setColor(Color.RED);
path = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int temp = 120;
canvas.drawLine(temp, temp, getMeasuredWidth() - temp, temp, paint);
paint.setStrokeCap(Paint.Cap.BUTT);
canvas.drawLine(temp, temp * 2, getMeasuredWidth() - temp, temp * 2, paint);
paint.setStrokeCap(Paint.Cap.SQUARE);
canvas.drawLine(temp, temp * 3, getMeasuredWidth() - temp, temp * 3, paint);
paint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawLine(temp, temp * 4, getMeasuredWidth() - temp, temp * 4, paint);
}
自定义进度条时,就可以直接画线了。
设置多次调用 Path.lineTo 这种线段之间连接处的样式。
示例如下:
public StrokeJoinCapView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
paint.setStrokeWidth(60);
paint.setStyle(Paint.Style.STROKE);
paint.setDither(true);
paint.setColor(Color.RED);
paint.setStrokeJoin(Paint.Join.MITER);
// paint.setStrokeJoin(Paint.Join.ROUND);
// paint.setStrokeJoin(Paint.Join.BEVEL);
path = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int temp = 120;
path.moveTo(temp, temp);
path.lineTo(getMeasuredWidth() - temp, temp);
path.lineTo(getMeasuredWidth() - temp, getMeasuredHeight() / 2);
path.lineTo(temp, getMeasuredHeight() / 2);
path.lineTo(temp, getMeasuredHeight() - temp);
path.lineTo(getMeasuredWidth() - temp, getMeasuredHeight() - temp);
canvas.drawPath(path, paint);
}
注意拐角处:
Paint.Join.MITER:
Paint.Join.ROUND:
Paint.Join.BEVEL:
系统给我们提供了六种效果,分别是 CornerPathEffect
、DashPathEffect
、DiscretePathEffect
、PathDashPathEffect
、ComposePathEffect
、SumPathEffect
。下面我们来一一介绍。
CornerPathEffect 的作用就是将原来的直线拐角变成圆形拐角,构造函数传入的就是拐角的半径。
/**
* @param radius 拐角处弧度半径
*/
public CornerPathEffect(float radius) {}
示例:
PathEffect pathEffect;
public StrokeJoinCapView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
paint.setStrokeWidth(30);
paint.setStyle(Paint.Style.STROKE);
paint.setDither(true);
paint.setColor(Color.RED);
path = new Path();
pathEffect = new CornerPathEffect(50);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int temp = 120;
path.moveTo(temp, temp);
path.lineTo(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
path.lineTo(getMeasuredWidth() - temp, temp);
paint.setPathEffect(pathEffect);
canvas.drawPath(path, paint);
}
效果图:
DashPathEffect 的作用就是实现 虚线效果。
/**
* @param 分割线的长度变化值数组,必须大于等于2
* @param phase 偏移大小
*/
public DashPathEffect(float intervals[], float phase) {}
示例:
int phase = 0;
PathEffect pathEffect;
public StrokeJoinCapView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.STROKE);
paint.setDither(true);
paint.setColor(Color.RED);
path = new Path();
float [] f = {20,10};
pathEffect = new DashPathEffect(f,phase);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int temp = 120;
path.moveTo(temp, temp);
path.lineTo(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
path.lineTo(getMeasuredWidth() - temp, temp);
paint.setPathEffect(pathEffect);
canvas.drawPath(path, paint);
}
效果图:
我们可以通过 修改 偏移值的大小来 实现如下效果:
@Override
protected void onDraw(Canvas canvas) {
...
float[] f = {20, 10};
pathEffect = new DashPathEffect(f, phase);
paint.setPathEffect(pathEffect);
canvas.drawPath(path, paint);
phase += 5;
postInvalidate();
}
/**
* @param segmentLength 每段线段长度
* @param deviation 偏移
*/
public DiscretePathEffect(float segmentLength, float deviation) { }
DiscretePathEffect 就是将原来路径分隔很多段 segmentLength
长的线段,然后将每条线段随机偏移 deviation
的位置,deviation
越大,抖动幅度越大,效果图如下:
示例:
public StrokeJoinCapView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.STROKE);
paint.setDither(true);
paint.setColor(Color.RED);
path = new Path();
pathEffect = new DiscretePathEffect(50, 50);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int temp = 120;
path.moveTo(temp, temp);
path.lineTo(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
path.lineTo(getMeasuredWidth() - temp, temp);
paint.setPathEffect(pathEffect);
canvas.drawPath(path, paint);
}
效果图:
/**
* @param shape 印戳的路径
* @param advance 每个印戳的距离
* @param phase 印戳的偏移大小
* @param style 每个印戳的变化规则
*/
public PathDashPathEffect(Path shape, float advance, float phase, Style style) {}
PathDashPathEffect 就是再原有路径上用 PathDashPathEffect 构造函数中的 shape 去绘制这条路径。提供了TRANSLATE、ROTATE、MORPH 这三种样式,主要区分拐角处。 效果如下:
示例:
public StrokeJoinCapView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.STROKE);
paint.setDither(true);
paint.setColor(Color.RED);
path = new Path();
dashPath = new Path();
dashPath.addCircle(0, 0, 10, Path.Direction.CCW);
dashPath.moveTo(20, 0);
dashPath.lineTo(0, 20);
dashPath.lineTo(40, 20);
dashPath.close();
pathEffect = new PathDashPathEffect(dashPath, 60, 0, PathDashPathEffect.Style.TRANSLATE);
// pathEffect = new PathDashPathEffect(dashPath, 60, 0, PathDashPathEffect.Style.ROTATE);
// pathEffect = new PathDashPathEffect(dashPath, 60, 0, PathDashPathEffect.Style.MORPH);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int temp = 120;
path.moveTo(temp, temp);
path.lineTo(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
path.lineTo(getMeasuredWidth() - temp, temp);
canvas.drawPath(path, paint);
canvas.translate(0, 100);
paint.setPathEffect(pathEffect);
canvas.drawPath(path, paint);
}
效果图,主要看拐角处:
这两个都是用来合并两个特效的。
/**
* (e.g. first(path) + second(path))
*/
public SumPathEffect(PathEffect first, PathEffect second) {}
/**
* (e.g. outer(inner(path))).
*/
public ComposePathEffect(PathEffect outerpe, PathEffect innerpe) {}
SumPathEffect 是分别对原始路径分别作用第一个特效和第二个特效。然后再将这两条路径合并,做为最终结果。可以理解为两个特效集合的并集。 ComposePathEffect 合并两个特效是有先后顺序的,它会先将第二个参数的PathEffect innerpe的特效作用于路径上,然后再在此加了特效的路径上作用第二个特效。可以理解为两个特效集合的交集。
示例:
public StrokeJoinCapView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.STROKE);
paint.setDither(true);
paint.setColor(Color.RED);
path = new Path();
pathEffect1 = new DiscretePathEffect(10, 10);
float[] f = {20, 10};
pathEffect2 = new DashPathEffect(f, 10);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int temp = 120;
path.moveTo(temp, temp);
path.lineTo(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
path.lineTo(getMeasuredWidth() - temp, temp);
canvas.drawPath(path, paint);
canvas.translate(0, 100);
paint.setPathEffect(new SumPathEffect(pathEffect1, pathEffect2));
canvas.drawPath(path, paint);
canvas.translate(0, 200);
paint.setPathEffect(new ComposePathEffect(pathEffect1, pathEffect2));
canvas.drawPath(path, paint);
}
效果图:
如果觉得不错的话,请帮忙点个赞呗。
以上