preface

Before entering the applet, there will be a loading animation, as shown below. The applet icon is in the center, and the outer circle is a green circle of progress, which will be drawn according to the loading progress.

The imitation effect is as follows

Here are the implementation steps

Draw a circular picture

The first step is to draw a round image, using Kotlin’s extension function to create a getCircledBitmap to get the rounded image of the Bitmap.

fun Bitmap.getCircledBitmap(): Bitmap {
    val output = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(output)
    val paint = Paint()
    val rect = Rect(0.0.this.width, this.height)
    paint.isAntiAlias = true
    canvas.drawARGB(0.0.0.0)
    canvas.drawCircle(this.width / 2f.this.height / 2f.this.width / 2f, paint)
    paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
    canvas.drawBitmap(this, rect, rect, paint)
    return output
}
Copy the code

Initialize the

Initialize in init function, create a Bitmap beforehand, repeat Runnable with postDelayed function, and internally increment startAngle and progress. StartAngle represents the starting Angle, because the circle keeps turning, progress represents progress, and when drawing an arc using drawArc, progress represents the Angle, and when 360 degrees are drawn, a complete circle is drawn.

class MiniLoading @JvmOverloads constructor(
    context: Context.attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    var progress: Float = 0f
    var startAngle: Float = 0f;
    val IMAGE_SIZE: Int = 162;
    val CIRCLE_SIZE: Float = ((IMAGE_SIZE / 2) + 20).toFloat()
    var bitmapLogo: Bitmap;
    init {
        var bitmap = BitmapFactory.decodeResource(resources, R.drawable.back)
        var matrix = Matrix()
        matrix.setScale(IMAGE_SIZE / bitmap.width.toFloat(), IMAGE_SIZE / bitmap.width.toFloat())
        bitmapLogo = Bitmap.createBitmap(bitmap, 0.0, bitmap.width, bitmap.height, matrix, false)
            .getCircledBitmap()
        var runnable = object : Runnable {
            override fun run(a) {
                startAngle += 5
                progress=if (progress>360) 0f else progress+2
                invalidate()
                postDelayed(this.1)
            }
        }
        postDelayed(runnable, 0)}Copy the code

Draw the content

The last step is to draw three sections in onDraw, the first is the middle image, the second is a light-colored “track”, and the third is the progress.

override fun onDraw(canvas: Canvas) {
    canvas.drawBitmap(
        bitmapLogo,
        (width / 2) - (IMAGE_SIZE / 2).toFloat(),
        -((bitmapLogo.height - height) / 2).toFloat(),
        Paint()
    )
    canvas.drawCircle(
        (width / 2).toFloat(),
        (height / 2).toFloat(),
        CIRCLE_SIZE,
        Paint().apply {
            style = Paint.Style.STROKE
            color = Color.parseColor("#E1DEE1")
        })
    val oval = RectF()
    oval.left = width / 2f - (CIRCLE_SIZE)
    oval.top = height / 2f - (CIRCLE_SIZE)
    oval.right = oval.left + CIRCLE_SIZE * 2
    oval.bottom = oval.top + CIRCLE_SIZE * 2
    canvas.drawArc(oval, startAngle, progress, false, Paint().apply {
        style = Paint.Style.STROKE
        strokeWidth = 5f
        color = Color.parseColor("#FF269F34")})Copy the code