自定义控件绘制(Paint函数汇总)篇五

参考:

  1. 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)
}
效果图

从图上看,BEVELROUND并没有明显区别;

setPathEffect

设置路径样式;取值类型是所有派生自PathEffect的子类;

1. CornerPathEffect-圆形拐角效果
将原来Path生硬的直线拐角,变成圆形拐角,从下图示

图片来自源博客

CornerPathEffect构造:

// radius 当前连接两条直线所使用的圆的半径
public CornerPathEffect(float radius)  
来自源博客,说明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 })
}
不同radius的CornerPathEffect效果

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)

之前都有接触过;

你可能感兴趣的:(自定义控件绘制(Paint函数汇总)篇五)