Blog Infos
Author
Published
Topics
,
Published

In the previous article we flew some jets to fight our enemies , in this article we will focus how to defend our country from enemies so we will create a radar to detect enemy jets.

note: you may need knowledge of canvas drawings in android as prerequisites for this article I’ll recommend to read below article before proceeding with this one article1article2article3article4.

Being Defensive

To create our radar I will draw a pie shape like below and then I can rotate this pie and it will look as a radar is scanning

To draw this shape I need the midpoint of the view and it’s height and width to draw the lines and need a path to draw the pie shape , we can do this onSizeChaned().

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    super.onSizeChanged(w, h, oldw, oldh)
    midPoint = width / 2f
    path.addArc(0f, 0f, width / 1f, height.toFloat(), -90f, 90f)
    path.lineTo(width / 2f, width / 2f)
}
override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        with(canvas) {
            drawPath(path, alphaPaint)
            drawLine(
                midPoint,
                midPoint, 
                width.toFloat(),
                midPoint, 
                linePaint)
            drawLine(midPoint, 
                midPoint,
                midPoint, 
                0f,
                linePaint)
        }
    }

here we are adding an arc from mid point to the edges of the screen it has an angle of 90 degrees we are also adding a line to path to close this path then we are invalidating to induce a call to onDraw() to draw our path and lines, then in the onDraw() we are drawing path and lines.

Couroutines for Animation

Using coroutines for animation is common in compose world but not much in the view world , let’s see how we can use coroutines in the view world.

var rotationAngle = 0f
CoroutineScope(context = Dispatchers.Default).launch {
    while (true) {
        delay(10)
        ++rotationAngle
        invalidate()
    }
}

Here I am creating a coroutine starting an infinite loop and increasing the rotation angle by 1 degrees and invalidating after every 10 milliseconds to induce a call to onDraw()

override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        with(canvas) {
            //rotating canvas 1 degrees in every 10 millis
            rotate(rotationAngle, midPoint, midPoint)
            drawPath(path, alphaPaint)
            drawLine(
                midPoint,
                midPoint,
                width.toFloat(),
                midPoint,
                linePaint)
            drawLine(midPoint,
                midPoint,
                midPoint,
                0f,
                linePaint)
        }
    }

 

 

well this is not enough fast jets can easily trespass from one part while the pie is scanning other part. I would like to add another layer of scanning to increase our security

For that I will draw a circle which continuously grows and shrinks in size, so how do we do that?

Trigonometry to the rescue

If you were like me in the high school thinking that when in life I am going to use this complex mathematics , I hated maths 😆

We will find answer to the old question now, because it turns out that we can use some high school trigonometry to solve our above problem.

source: https://byjus.com/maths/trigonometry-graphs/

If you remember this is sine graph in the above image the range of sine is [-1,1] means you can keep on increasing the angle but the value of sine will keep on oscillating between -1 and 1, it goes from -1 to 1 and 1 to -1 as evident by the above graph.

So if I take an angle variable whose value is incremented in our coroutine then take the sin I will keep getting value from -1 to 1 and if I multiply these values to width/2 I can get the radius of my circle whose range will come be [-width/2,width/2] , a negative radius does not make sense so I will take the absolute value of sine itself so the range will be [0,width/2]

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    super.onSizeChanged(w, h, oldw, oldh)
    var degrees = 0L
    CoroutineScope(context = Dispatchers.Default).launch {
        while (true) {
            delay(10)
            ++degrees
            ++rotationAngle
            val angleRadians = Math.toRadians(degrees.toDouble())
            val sine = abs(sin(angleRadians)).toFloat()
            pulseRadius = width / 2f * sine
            invalidate()
        }
    }
}

 

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

,

Coroutine-Driven Android Billing- Use Cases, Fallbacks, and Functional Programming

In this technical deep-dive, I share my hands-on experience rewriting the Google play billing integration for Hinge. Our overhaul paved the way for faster feature integrations and reduced refunds.
Watch Video

Coroutine-Driven Android Billing- Use Cases, Fallbacks, and Functional Programming

Ryan Newsom
Staff Android Engineer
Hinge

Coroutine-Driven Android Billing- Use Cases, Fallbacks, and Functional Programming

Ryan Newsom
Staff Android Engine ...
Hinge

Coroutine-Driven Android Billing- Use Cases, Fallbacks, and Functional Programming

Ryan Newsom
Staff Android Engineer
Hinge

Jobs

here I am calculating the radius and assigning to a global variable then invalidating to draw the circle.

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    with(canvas) {
        rotate(rotationAngle, midPoint, midPoint)
        drawPath(path, alphaPaint)
        drawLine(
            midPoint,
            midPoint,
            width.toFloat(),
            midPoint,
            linePaint)
        drawLine(midPoint,
            midPoint,
            midPoint,
            0f,
           linePaint)
     //DRAW OUR CIRCLE 
     drawCircle(midPoint, midPoint, pulseRadius, alphaPaint)
    }
}

 

 

 

cool now let’s add our jets from the previous article and add the background to create a war zone

 

 

if you find it interesting you can find complete code at my github

thanks, have a good day 😊

This article was originally published on proandroiddev.com on July 06, 2022

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog

How to animate BottomSheet content using Jetpack Compose

Early this year I started a new pet project for listening to random radio…
READ MORE
blog
The LookaheadScope (replaced by the previous LookaheadLayout) is a new experimental API in Jetpack…
READ MORE
blog
Expandable views are a common way to hide details of a visualised data structures.…
READ MORE
blog
Working with user interfaces sometimes is not an easy job. On Android you have…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu