美文网首页
自定义控件绘制(Paint函数汇总)篇五

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

作者: zhaoyubetter | 来源:发表于2018-04-06 17:25 被阅读136次

    参考:

    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函数汇总)篇五

          本文链接:https://www.haomeiwen.com/subject/kzijhftx.html