Android自定义View--转圈圈

Android自定义View–转圈圈

Android自定义View--转圈圈_第1张图片
看GIF图说话,用代码实现这个效果

Android自定义View--转圈圈_第2张图片
先以圆心a 画半径100的圆,在画一个半径150的圆c,以圆c上的点为半径画圆b,每隔5度画一个圆b,之后根据画圆b时的角度在圆b上画一个圆d,当大于180度时画圆的角度要用360度减去当前的度数。

首先肯定是测量View的大小了

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        var w = 0
        var h = 0
        val wMode = MeasureSpec.getMode(widthMeasureSpec)
        if (wMode == MeasureSpec.AT_MOST) {
            w = widthC+paddingLeft+paddingRight
        } else if (wMode == MeasureSpec.EXACTLY) {
            w = MeasureSpec.getSize(widthMeasureSpec)+paddingLeft+paddingRight
        }
        val hMode = MeasureSpec.getMode(heightMeasureSpec)
        if (hMode == MeasureSpec.AT_MOST) {
            h = hightC+paddingTop+paddingBottom
        } else if (hMode == MeasureSpec.EXACTLY) {
            h = MeasureSpec.getSize(heightMeasureSpec)+paddingTop+paddingBottom
        }
        widthC = w
        hightC = h
        setMeasuredDimension(
            MeasureSpec.makeMeasureSpec(w, wMode),
            MeasureSpec.makeMeasureSpec(h, hMode)
        )
    }

计算圆上的坐标

pointX = x + radius * Math.cos(Math.toRadians(angle))//angle是弧度
pointY = y + radius * Math.sin(Math.toRadians(angle))

画出圆b

    val realW = widthC - paddingLeft - paddingRight
    val realH = hightC - paddingTop - paddingBottom
    val centerRadius: Double = min(realW, realH) * 0.1875  //0.1875是计算圆c的半径 一个比例 150/800=0.1875    
    val circleRadius=min(realW, realH) * 0.3125 //0.3125是计算圆b的半径的一个比例  250/800=0.3125
    for (i in 0..360 step 5) {//每5度画一个圆
        val circleX =
            ((centerRadius * cos(
                Math.toRadians(
                    i.toDouble()
                )
            )) + widthC / 2f).toFloat()
        val circleY =
            ((centerRadius * sin(Math.toRadians(i.toDouble()))) + hightC / 2f).toFloat()
        canvas?.drawCircle(circleX, circleY, circleRadius.toFloat(), circlePaint)
    }

通过上面画出一下的圆
Android自定义View--转圈圈_第3张图片
在通过一下代码将圆d画到圆b上

        canvas?.drawCircle(
            ((circleRadius * cos(
                Math.toRadians(
                    if (i in 0..180 && i == 360) getOffset(i) else getOffset(
                        360 - i
                    )
                )
            )) + circleX).toFloat(),
            (circleRadius * sin(
                Math.toRadians(
                    if (i in 0..180 && i == 360) getOffset(i) else getOffset(
                        360 - i
                    )
                )
            ) + circleY).toFloat(),
            5f,
            dotPaint
        )
   /**
     *@param i
     * @param s 圆点的初始角度 默认0
     */
    private fun getOffset(i: Int,s:Int=0): Double = (if (i == 360) {
        0 + offset % 360+s
    } else {
        i + offset % 360+s
    }).toDouble()

这样就画好了,如下图

Android自定义View--转圈圈_第4张图片
最后去掉蓝色圆,添加计时器每16ms重绘一次,这样就可以动起来了

private var offset = 360

Timer().schedule(object : TimerTask() {
            override fun run() {
                offset++
                invalidate()
            }
        }, 16, 16)

还可以弄成下面的样式:

Android自定义View--转圈圈_第5张图片
Android自定义View--转圈圈_第6张图片

你可能感兴趣的:(Android自定义View--转圈圈)