高模倣キビローディングアニメーション効果

序文

まず、Xiaomiの読み込みアニメーションを見てみましょう。これは単なる写真ですが、すべてを記録することはできないため、読み込まれるとすぐに成功するものが多く、私には表示されません。チャンスがあれば、スクリーンショットを撮るだけですが、彼の読み込みアニメーションの特徴は、左側の円が回転し続けることです。

image.png

模倣効果は次のとおりです。

画面録画_selectarea_20210917141950.gif

実装プロセス

これは難しいことではありません。式を学ぶだけです。つまり、中心、半径、角度を知り、円上の点の座標を見つけます。計算結果は、この点で実線の円を描くことができます。以下はカスタムダイアログです。 、それをしましょう一番下の現実では、ビューもカスタムビューです。


class MiuiLoadingDialog(context: Context) : Dialog(context) {
    private var miuiLoadingView : MiuiLoadingView= MiuiLoadingView(context);
    init {
        setContentView(miuiLoadingView)
        setCancelable(false)
    }

    override fun show() {
        super.show()
        val window: Window? = getWindow();
        val wlp = window!!.attributes

        wlp.gravity = Gravity.BOTTOM
        window.setBackgroundDrawable( ColorDrawable(Color.TRANSPARENT));
        wlp.width=WindowManager.LayoutParams.MATCH_PARENT;
        window.attributes = wlp
    }
}
复制代码

主なロジックは次のとおりです。まずclipPath、メソッドで角の丸い形状を切り出し、次に固定された外側の円を描きます。

真ん中の円には、次のような式が必要です。

x1   =   x0   +   r   *   cos(a   *   PI   /180   ) 
y1   =   y0   +   r   *   sin(a   *   PI  /180   ) 
复制代码

x0とy0は外側の大きな円の中心点、rは中央の小さな円のサイズ、aは角度です。この角度を変更し続けるだけで、得られたx1とy1を次のように描くことができます。 drawCircle。

image.png


class MiuiLoadingView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    //Dialog上面圆角大小
    val CIRCULAR: Float = 60f;

    //中心移动圆位置
    var rx: Float = 0f;
    var ry: Float = 0f;

    //左边距离
    var MARGIN_LEFT: Int = 100;

    //中心圆大小
    var centerRadiusSize: Float = 7f;

    var textPaint: Paint = Paint().apply {
        textSize = 50f
        color = Color.BLACK
    }

    var circlePaint: Paint = Paint().apply {
        style = Paint.Style.STROKE
        strokeWidth = 8f
        isAntiAlias = true
        color = Color.BLACK
    }

    var centerCirclePaint: Paint = Paint().apply {
        style = Paint.Style.FILL
        isAntiAlias = true
        color = Color.BLACK
    }

    var degrees = 360;

    val TEXT = "正在加载中,请稍等";
    var textHeight = 0;

    init {

        var runnable = object : Runnable {
            override fun run() {
                val r = 12;
                rx = MARGIN_LEFT + r * Math.cos(degrees.toDouble() * Math.PI / 180).toFloat()
                ry =
                    ((measuredHeight.toFloat() / 2) + r * Math.sin(degrees.toDouble() * Math.PI / 180)).toFloat();
                invalidate()
                degrees += 5
                if (degrees > 360) degrees = 0
                postDelayed(this, 1)
            }
        }
        postDelayed(runnable, 0)


        var rect = Rect()
        textPaint.getTextBounds(TEXT, 0, TEXT.length, rect)
        textHeight = rect.height()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        setMeasuredDimension(widthMeasureSpec, 220);
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        var path = Path()
        path.addRoundRect(
            RectF(0f, 0f, measuredWidth.toFloat(), measuredHeight.toFloat()),
            floatArrayOf(CIRCULAR, CIRCULAR, CIRCULAR, CIRCULAR, 0f, 0f, 0f, 0f), Path.Direction.CW
        );
        canvas.clipPath(path)
        canvas.drawColor(Color.WHITE)


        canvas.drawCircle(
            MARGIN_LEFT.toFloat(), measuredHeight.toFloat() / 2,
            35f, circlePaint
        )

        canvas.drawCircle(
            rx, ry,
            centerRadiusSize, centerCirclePaint
        )


        canvas.drawText(TEXT, (MARGIN_LEFT + 80).toFloat(), ((measuredHeight / 2)+(textHeight/2)).toFloat(), textPaint)
    }
}

复制代码

おすすめ

転載: juejin.im/post/7008788268128927757