自定义view之网状图

小牛试刀,花了一个小时写了个网状图,如下
这里写图片描述
绘制的思路分成三部
1,首先绘制三条连接的长的直线,代码如下

    //画第一条竖线
        canvas.drawLine(0f, -r, 0f, r, mPaintLineBg)
        val averageAngle = 360f / PART

        val y = (Math.sin(averageAngle / 2 / 180 * Math.PI) * r).toFloat()
        val x = (Math.cos(averageAngle / 2 / 180 * Math.PI) * r).toFloat()
        //斜线1
        canvas.drawLine(-x, y, x, -y, mPaintLineBg)
        //斜线2
        canvas.drawLine(-x, -y, x, y, mPaintLineBg)

2,然后绘制四个正六边形

 for (i in 1..4) {
            val xx = x * i / 4
            val yy = y * i / 4
            val rr = r * i / 4
            val path = Path()
            path.moveTo(0f, rr)
            path.lineTo(xx, yy)
            path.lineTo(xx, -yy)
            path.lineTo(0f, -rr)
            path.lineTo(-xx, -yy)
            path.lineTo(-xx, yy)
            path.close()
            canvas.drawPath(path, mPaintLineBg)
        }

最后绘制区域图形

  val path = Path()
        if (topRaw == 0f) {
            path.moveTo(0f, 0f)
        } else {
            path.moveTo(0f, -r * topRaw)
            canvas.drawCircle(0f, -r * topRaw, circleRaduis, mPaintCirlce)
        }
        if (topRightRaw == 0f) {
            path.lineTo(0f, 0f)
        } else {
            val y2 = (Math.sin(averageAngle / 2 / 180 * Math.PI) * (r * topRightRaw)).toFloat()
            val x2 = (Math.cos(averageAngle / 2 / 180 * Math.PI) * (r * topRightRaw)).toFloat()
            path.lineTo(x2, -y2)
            canvas.drawCircle(x2, -y2, circleRaduis, mPaintCirlce)
        }
        if (bottomRightRaw == 0f) {
            path.lineTo(0f, 0f)
        } else {
            val y3 = (Math.sin(averageAngle / 2 / 180 * Math.PI) * (r * bottomRightRaw)).toFloat()
            val x3 = (Math.cos(averageAngle / 2 / 180 * Math.PI) * (r * bottomRightRaw)).toFloat()
            path.lineTo(x3, y3)
            canvas.drawCircle(x3, y3, circleRaduis, mPaintCirlce)
        }

        if (bottomRaw == 0f) {
            path.moveTo(0f, 0f)
        } else {
            path.lineTo(0f, r * bottomRaw)
            canvas.drawCircle(0f, r * bottomRaw, circleRaduis, mPaintCirlce)
        }
        if (bottomLeftRaw == 0f) {
            path.lineTo(0f, 0f)
        } else {
            val y4 = (Math.sin(averageAngle / 2 / 180 * Math.PI) * (r * bottomLeftRaw)).toFloat()
            val x4 = (Math.cos(averageAngle / 2 / 180 * Math.PI) * (r * bottomLeftRaw)).toFloat()
            path.lineTo(-x4, y4)
            canvas.drawCircle(-x4, y4, circleRaduis, mPaintCirlce)
        }
        if (topLeftRaw == 0f) {
            path.lineTo(0f, 0f)
        } else {
            val y5 = (Math.sin(averageAngle / 2 / 180 * Math.PI) * (r * topLeftRaw)).toFloat()
            val x5 = (Math.cos(averageAngle / 2 / 180 * Math.PI) * (r * topLeftRaw)).toFloat()
            path.lineTo(-x5, -y5)
            canvas.drawCircle(-x5, -y5, circleRaduis, mPaintCirlce)
        }
        path.close()
        canvas.drawPath(path, mPaintLine)

最后贴上所有代码

class SpiderView @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    companion object {
        val PART = 6
    }

    //画背景的
    private val mPaintLineBg = Paint(Paint.ANTI_ALIAS_FLAG)
    //画区域
    private val mPaintLine = Paint(Paint.ANTI_ALIAS_FLAG)
    //
    private val mPaintCirlce = Paint(Paint.ANTI_ALIAS_FLAG)
    // 宽高
    private var mWidth: Int = 0
    private var mHeight: Int = 0
    //中心的坐标
    private var mCenterX: Int = 0
    private var mCenterY: Int = 0
    //总进度
    private var count: Int = 100
    private var topRaw: Float = 0f
    private var topRightRaw: Float = 0f
    private var bottomRightRaw: Float = 0f
    private var bottomRaw: Float = 0f
    private var bottomLeftRaw: Float = 0f
    private var topLeftRaw: Float = 0f
    private val circleRaduis: Float = dp2px(3f)

    init {
        mPaintLineBg.color = Color.parseColor("#0000EE")
        mPaintLineBg.style = Paint.Style.STROKE
        mPaintLineBg.strokeWidth = dp2px(0.5f)

        mPaintLine.style = Paint.Style.FILL
        mPaintLine.color = Color.parseColor("#aaB22222")

        mPaintCirlce.style = Paint.Style.FILL
        mPaintCirlce.color = Color.parseColor("#0000EE")
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val width = measureWidth(widthMeasureSpec)
        val height = measureHeight(heightMeasureSpec)
        val imageSize = if (width < height) width else height
        setMeasuredDimension(imageSize, imageSize)

    }

    /**
     * 测量宽度
     */
    private fun measureWidth(measureSpec: Int): Int {
        val result: Int
        val specMode = View.MeasureSpec.getMode(measureSpec)
        val specSize = View.MeasureSpec.getSize(measureSpec)

        if (specMode == View.MeasureSpec.EXACTLY) {
            result = specSize
        } else if (specMode == View.MeasureSpec.AT_MOST) {
            result = specSize
        } else {
            result = specSize
        }
        return result
    }

    /**
     * 测量高度
     */
    private fun measureHeight(measureSpecHeight: Int): Int {
        val result: Int
        val specMode = View.MeasureSpec.getMode(measureSpecHeight)
        val specSize = View.MeasureSpec.getSize(measureSpecHeight)

        if (specMode == View.MeasureSpec.EXACTLY) {
            result = specSize
        } else if (specMode == View.MeasureSpec.AT_MOST) {
            result = specSize
        } else {
            result = specSize
        }
        return result
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mWidth = w;
        mHeight = h;
        mCenterX = mWidth / 2
        mCenterY = mHeight / 2
    }

    @SuppressLint("DrawAllocation")
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.translate(mCenterX.toFloat(), mCenterY.toFloat())
        val r = Math.min(mCenterX, mCenterY).toFloat()
        //画第一条竖线
        canvas.drawLine(0f, -r, 0f, r, mPaintLineBg)
        val averageAngle = 360f / PART

        val y = (Math.sin(averageAngle / 2 / 180 * Math.PI) * r).toFloat()
        val x = (Math.cos(averageAngle / 2 / 180 * Math.PI) * r).toFloat()
        //斜线1
        canvas.drawLine(-x, y, x, -y, mPaintLineBg)
        //斜线2
        canvas.drawLine(-x, -y, x, y, mPaintLineBg)
        for (i in 1..4) {
            val xx = x * i / 4
            val yy = y * i / 4
            val rr = r * i / 4
            val path = Path()
            path.moveTo(0f, rr)
            path.lineTo(xx, yy)
            path.lineTo(xx, -yy)
            path.lineTo(0f, -rr)
            path.lineTo(-xx, -yy)
            path.lineTo(-xx, yy)
            path.close()
            canvas.drawPath(path, mPaintLineBg)
        }

        val path = Path()
        if (topRaw == 0f) {
            path.moveTo(0f, 0f)
        } else {
            path.moveTo(0f, -r * topRaw)
            canvas.drawCircle(0f, -r * topRaw, circleRaduis, mPaintCirlce)
        }
        if (topRightRaw == 0f) {
            path.lineTo(0f, 0f)
        } else {
            val y2 = (Math.sin(averageAngle / 2 / 180 * Math.PI) * (r * topRightRaw)).toFloat()
            val x2 = (Math.cos(averageAngle / 2 / 180 * Math.PI) * (r * topRightRaw)).toFloat()
            path.lineTo(x2, -y2)
            canvas.drawCircle(x2, -y2, circleRaduis, mPaintCirlce)
        }
        if (bottomRightRaw == 0f) {
            path.lineTo(0f, 0f)
        } else {
            val y3 = (Math.sin(averageAngle / 2 / 180 * Math.PI) * (r * bottomRightRaw)).toFloat()
            val x3 = (Math.cos(averageAngle / 2 / 180 * Math.PI) * (r * bottomRightRaw)).toFloat()
            path.lineTo(x3, y3)
            canvas.drawCircle(x3, y3, circleRaduis, mPaintCirlce)
        }

        if (bottomRaw == 0f) {
            path.moveTo(0f, 0f)
        } else {
            path.lineTo(0f, r * bottomRaw)
            canvas.drawCircle(0f, r * bottomRaw, circleRaduis, mPaintCirlce)
        }
        if (bottomLeftRaw == 0f) {
            path.lineTo(0f, 0f)
        } else {
            val y4 = (Math.sin(averageAngle / 2 / 180 * Math.PI) * (r * bottomLeftRaw)).toFloat()
            val x4 = (Math.cos(averageAngle / 2 / 180 * Math.PI) * (r * bottomLeftRaw)).toFloat()
            path.lineTo(-x4, y4)
            canvas.drawCircle(-x4, y4, circleRaduis, mPaintCirlce)
        }
        if (topLeftRaw == 0f) {
            path.lineTo(0f, 0f)
        } else {
            val y5 = (Math.sin(averageAngle / 2 / 180 * Math.PI) * (r * topLeftRaw)).toFloat()
            val x5 = (Math.cos(averageAngle / 2 / 180 * Math.PI) * (r * topLeftRaw)).toFloat()
            path.lineTo(-x5, -y5)
            canvas.drawCircle(-x5, -y5, circleRaduis, mPaintCirlce)
        }
        path.close()
        canvas.drawPath(path, mPaintLine)
    }

    private fun sp2px(spValue: Float): Float {
        val fontScale = resources.displayMetrics.scaledDensity
        return (spValue * fontScale + 0.5f)
    }

    private fun dp2px(dp: Float): Float {
        val scale = resources.displayMetrics.density
        return (dp * scale + 0.5f)
    }

    public fun setProgress(top: Int, topRight: Int, bottomRight: Int, bottom: Int, bottomLeft: Int, topLeft: Int) {
        topRaw = (top * 1f / count)
        bottomRightRaw = (bottomRight * 1f / count)
        bottomRaw = (bottom * 1f / count)
        bottomLeftRaw = (bottomLeft * 1f / count)
        topLeftRaw = (topLeft * 1f / count)
        topRightRaw = (topRight * 1f / count)
        invalidate()
    }

    public fun setCount(count: Int) {
        this.count = count
    }

}

猜你喜欢

转载自blog.csdn.net/villa_mou/article/details/78980404
今日推荐