Paint的setStrokeCap、setStrokeJoin、setPathEffect

转载请以链接形式标明出处:
本文出自:103style的博客


setStrokeCap

设置画笔的线冒样式:

  • Paint.Cap.BUTT:无
  • Paint.Cap.SQUARE:方形
  • Paint.Cap.ROUND: 半圆形

注意: Paint.Cap.ROUNDPaint.Cap.SQUARE 会在线长度的基础上首尾添加一个通过 setStrokeWidth 设置的宽度。

示例如下:依次为 无设置Paint.Cap.BUTTPaint.Cap.SQUAREPaint.Cap.ROUND
可以看到 ROUNDSQUARE 样式的明显长一点。

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);
}

setStrokeCap

自定义进度条时,就可以直接画线了。


setStrokeJoin

设置多次调用 Path.lineTo 这种线段之间连接处的样式。

  • Paint.Join.MITER: 直角的样式
  • Paint.Join.ROUND:圆弧
  • Paint.Join.BEVEL:在直角样式上切了一个小三角形

示例如下:

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.MITERPaint.Join.MITER
Paint.Join.ROUNDPaint.Join.ROUND
Paint.Join.BEVELPaint.Join.BEVEL


setPathEffect

系统给我们提供了六种效果,分别是 CornerPathEffectDashPathEffectDiscretePathEffectPathDashPathEffectComposePathEffectSumPathEffect。下面我们来一一介绍。
系统提供的六种PathEffect

CornerPathEffect

CornerPathEffect 的作用就是将原来的直线拐角变成圆形拐角,构造函数传入的就是拐角的半径。

/**
 * @param radius 拐角处弧度半径
 */
public CornerPathEffect(float radius) {}

摘自 https://blog.csdn.net/harvic880925/article/details/51010839

示例:

    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);
}

效果图:CornerPathEffect


DashPathEffect

DashPathEffect 的作用就是实现 虚线效果。

/**
 * @param 分割线的长度变化值数组,必须大于等于2
 * @param phase  偏移大小
 */
public DashPathEffect(float intervals[], float phase) {}

摘自 https://blog.csdn.net/harvic880925/article/details/51010839

示例:

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);
}

效果图:DashPathEffect

我们可以通过 修改 偏移值的大小来 实现如下效果:

@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();
}

修改偏移值再重绘


DiscretePathEffect

/**
 * @param segmentLength 每段线段长度
 * @param deviation     偏移
 */
public DiscretePathEffect(float segmentLength, float deviation) { }

DiscretePathEffect 就是将原来路径分隔很多段 segmentLength 长的线段,然后将每条线段随机偏移 deviation 的位置,deviation 越大,抖动幅度越大,效果图如下:
摘自 https://blog.csdn.net/harvic880925/article/details/51010839

示例:

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);
}

效果图:DiscretePathEffect(10,10)

DiscretePathEffect(10,50)


PathDashPathEffect

/**
 * @param shape   印戳的路径
 * @param advance 每个印戳的距离
 * @param phase   印戳的偏移大小
 * @param style   每个印戳的变化规则
 */
public PathDashPathEffect(Path shape, float advance, float phase, Style style) {}

PathDashPathEffect 就是再原有路径上用 PathDashPathEffect 构造函数中的 shape 去绘制这条路径。提供了TRANSLATEROTATEMORPH 这三种样式,主要区分拐角处。
效果如下:
摘自 https://blog.csdn.net/harvic880925/article/details/51010839

示例:

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);
}

效果图,主要看拐角处:PathDashPathEffect  PathDashPathEffect.Style.TRANSLATE
PathDashPathEffect  PathDashPathEffect.Style.ROTATE
PathDashPathEffect  PathDashPathEffect.Style.MORPH


SumPathEffect和 ComposePathEffect

这两个都是用来合并两个特效的。

/**
 * (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);
}

效果图:SumPathEffect 和 ComposePathEffect


参考文章


如果觉得不错的话,请帮忙点个赞呗。

以上


扫描下面的二维码,关注我的公众号 Android1024, 点关注,不迷路。
Android1024

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章