• 一:图形的位置和尺寸测量


    绘制的基本要素:

    onDraw(Canvas):是用来重写的

    Canvas:实际执行绘制的

    Paint:调整粗细和颜色等

    坐标系:以屏幕左上角为原点,向右、向下为正向数值的坐标系

    尺寸单位:在绘制过程中所有的尺寸单位都是px,像素,在绘制阶段是直接跟屏幕打交道的

    举例,我们画一条线

    package com.example.viewtest.view
    
    import android.content.Context
    import android.graphics.Canvas
    import android.graphics.Paint
    import android.util.AttributeSet
    import android.view.View
    
    class TestView(context: Context, attrs: AttributeSet) : View(context, attrs) {
    
        private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    
        override fun onDraw(canvas: Canvas) {
            super.onDraw(canvas)
            canvas.drawLine(100f, 100f, 300f, 300f, paint)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    画个圆

    package com.example.viewtest.view
    
    import android.content.Context
    import android.graphics.Canvas
    import android.graphics.Paint
    import android.util.AttributeSet
    import android.view.View
    import com.example.viewtest.ext.dp
    
    class TestView(context: Context, attrs: AttributeSet) : View(context, attrs) {
    
        private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    
        override fun onDraw(canvas: Canvas) {
            super.onDraw(canvas)
    
            canvas.drawCircle(width / 2f, height / 2f, 100.dp, paint)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    接下来讲Path,path不是用来绘制路径的,绘制路径只是其中一个功能而已,他是用来绘制图形的

    使用Path绘制一个圆

    package com.example.viewtest.view
    
    import android.content.Context
    import android.graphics.Canvas
    import android.graphics.Paint
    import android.graphics.Path
    import android.util.AttributeSet
    import android.view.View
    import com.example.viewtest.ext.dp
    
    class TestView(context: Context, attrs: AttributeSet) : View(context, attrs) {
    
        private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    
        private val path = Path()
    
        // 在尺寸发生改变的时候,初始化 path
        override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
            super.onSizeChanged(w, h, oldw, oldh)
            path.reset()
            // 最后一个参数:Direction,CW:顺时针,CCW:逆时针
            path.addCircle(width / 2f, height / 2f, 100.dp, Path.Direction.CW)
        }
    
        override fun onDraw(canvas: Canvas) {
            super.onDraw(canvas)
    //        canvas.drawLine(100f, 100f, 300f, 300f, paint)
    //
    //        canvas.drawCircle(width / 2f, height / 2f, 100.dp, paint)
    
            canvas.drawPath(path, paint)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    这里主要讲一下Direction,Direction主要是用来处理两个图形相交处的样子,通过Direction的配合使用,可以使图形相交地方之处实现实心还是镂空的效果,这里有一个标准

    如果要确定一个点是在内部还是外部,那么就从这个点像任意方向发送一条射线,这条线遇到左旋(逆时针)路径就+1,右旋路径就-1,最终结果无论正负,只要不为0,那么这就是一个在内部的点

    除此之外,一般使用path.fillType属性,他的默认值Path.FillType.WINDING,使用path.fillType是另一套计算方式,也就是说不管左旋还是右旋,一个点只记录和path的相交次数,奇数为内部,偶数为外部

    镂空效果直接设置为 path.fillType = Path.FillType.EVEN_ODD

    举个例子,一个圆和一个方相交

    package com.example.viewtest.view
    
    import android.content.Context
    import android.graphics.Canvas
    import android.graphics.Paint
    import android.graphics.Path
    import android.util.AttributeSet
    import android.view.View
    import com.example.viewtest.ext.dp
    
    class TestView(context: Context, attrs: AttributeSet) : View(context, attrs) {
    
        private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    
        private val path = Path()
    
        // 在尺寸发生改变的时候,初始化 path
        override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
            super.onSizeChanged(w, h, oldw, oldh)
            path.reset()
            // 最后一个参数:Direction,CW:顺时针,CCW:逆时针
            path.addCircle(width / 2f, height / 2f, 100.dp, Path.Direction.CW)
    
            path.addRect(width / 2f - 100.dp, height / 2f, width / 2f + 100.dp, height / 2f + 2 * 100.dp, Path.Direction.CCW)
            // 第二个参数的作用是是否要自动闭合
            pathMeasure = PathMeasure(path, false)
            
            pathMeasure.length
            // 给定一个长度,会返回当前长度所处位置的切点,也就是正弦值
            pathMeasure.getPosTan()
    
            path.fillType = Path.FillType.EVEN_ODD
        }
    
        override fun onDraw(canvas: Canvas) {
            super.onDraw(canvas)
    //        canvas.drawLine(100f, 100f, 300f, 300f, paint)
    //
    //        canvas.drawCircle(width / 2f, height / 2f, 100.dp, paint)
    
            canvas.drawPath(path, paint)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    pathMeasure = PathMeasure(path, false)

    第二个参数的作用是是否要自动闭合,如果一个图形假设是个半圆,那么测量的就是这个半圆的长度,如果是true就是半圆+起始点连接线的长度

  • 相关阅读:
    【机器学习算法】神经网络与深度学习-9 递归神经网络
    第七部分:Maven(项目管理工具)
    tab切换(用jQuery实现)?
    lua基础之位操作
    微信小程序通过官方内置函数实现WebSocket
    Go语言的跨文件调包
    2023年11月数据库流行度最新排名
    git常用命令
    Linux 调试之strace
    hevc vps解析
  • 原文地址:https://blog.csdn.net/qq_35178391/article/details/132725491