CodeFlys
12/20/2019 - 12:16 PM

DashboardView

class DashboardView @JvmOverloads constructor(
    context: Context, @Nullable attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    defStyleRes: Int = 0
) : View(context, attrs, defStyleAttr, defStyleRes) {
    private val paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val path: Path = Path()
    private val bounds: RectF = RectF()
    private val radius: Float = dp2px(150F)
    private val openAngle: Float = 120F
    private val startAngle: Float = 90 + openAngle / 2
    private val sweepAngle: Float = 360 - openAngle
    private val pathMeasure: PathMeasure = PathMeasure()
    private val markLength: Float = dp2px(120F)
    private val markCount: Int = 9
    private val markIndex: Int = 6
    private lateinit var pathDashPathEffect: PathDashPathEffect
    private val dashPath: Path = Path()


    init {
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = dp2px(3F)
        dashPath.addRect(RectF(0F, 0F, dp2px(3F), dp2px(9F)), Path.Direction.CW)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        path.reset()
        bounds.set(width / 2 - radius, height / 2 - radius, width / 2 + radius, height / 2 + radius)
        path.addArc(bounds, startAngle, sweepAngle)
        pathMeasure.setPath(path, false)
        val length = pathMeasure.length
        pathDashPathEffect = PathDashPathEffect(
            dashPath,
            (length - dp2px(3F)) / (markCount - 1),
            0F,
            PathDashPathEffect.Style.ROTATE
        )
    }


    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.drawPath(path, paint)
        paint.pathEffect = pathDashPathEffect
        canvas.drawPath(path, paint)
        paint.pathEffect = null
        canvas.drawLine(
            width / 2F,
            height / 2F,
            (width / 2F + markLength * Math.cos(Math.toRadians((startAngle + sweepAngle / (markCount - 1) * markIndex).toDouble()))).toFloat(),
            (height / 2F + markLength * Math.sin(Math.toRadians((startAngle + sweepAngle / (markCount - 1) * markIndex).toDouble()))).toFloat(),
            paint
        )
    }


    private fun dp2px(dp: Float) = TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        dp,
        Resources.getSystem().displayMetrics
    )
}