Draw a Circle Android Cnavas

Canvas animations: Elementary Circle Progress View on Android

Photo by Daniel Cheung on Unsplash

Photo by Daniel Cheung on Unsplash

The Android Class form lets us draw anything* that we can imagine using basic shapes, paths, and bitmaps. The Canvass API information technology's actually big 🤯 and daunting at kickoff sight. Hither we're just going to scratch the surface to create our simple animation.

The animation

Full circle progress animation

Note

This article will be covering each footstep for conceiving the animation but I do recommend reading a bit further: Getting started with cartoon on the Android Canvas by Rebecca Franks it's a bang-up read 🤓.

Ok, lets started!

Yous may know the drill. Create a new project, with an empty action, and create a class that extends from the AndroidView class:

          class CircularProgressView(
context: Context?,
attrs: AttributeSet?
) : View(context, attrs) {}

And at present we take our ready to draw on view! 🙌

What practise we need to describe?

In gild to reach this animation we first accept to know how to describe the circles, we need one to be the groundwork and another arc to fill the electric current progress.

Background arc at the left and inner arc to marker the progress at the correct.

And how can we draw it?

Each view comes with a onDraw method override which provides usa with a Sail instance for u.s. to get-go drawing with. To achieve our animation we need to create draw two arcs using the canvas case, i arc for the groundwork, and one of the tops, which will exist the one to be animated. For that, we'll demand to utilize the Canvas#drawArcmethod, which tin can let us draw a circle with nothing on the inside.

Let's take a wait into it 🖌.

          public void drawArc (
RectF oval,
float startAngle,
float sweepAngle,
boolean useCenter,
Paint pigment
)

Nice, merely what do they mean?

  • The RectF oval is merely a holder for the coordinates needed to create an "invisible rectangle" in which our oval volition be contained. This oval is used to define the shape and size of the arc.
  • startAngle: is the degree starting point from our oval from where we are going to start drawing the arc.
  • sweepAngle: means how much of the arc is going to be painted from the startAngle to this bending.
  • useCenter: the documentation explains information technology as, if truthful, include the center of the oval in the arc, and close it if information technology is being stroked. This will draw a wedge.
  • paint: this is the object that provides the data to the drawing of how information technology should be stroked, it's color, and more.

Drawing the background circle 🎨

Now that we understand what we need in guild to draw an arc, let's become to the code.

In our view's onDraw method we should create our oval's RectF infinite with the correct dimensions we desire our circle progress to have:

          // ...          private val ovalSpace = RectF()                    override fun onDraw(canvas: Canvas?) {
setSpace()
}private fun setSpace() {
val horizontalCenter = (width.div(2)).toFloat()
val verticalCenter = (tiptop.div(2)).toFloat()
val ovalSize = 200
ovalSpace.set(
horizontalCenter - ovalSize,
verticalCenter - ovalSize,
horizontalCenter + ovalSize,
verticalCenter + ovalSize
)
}

Equally this won't be painted information technology would simply represent an invisible oval space similar the following:

Invisible oval space representation.

Later we take our oval space we can use the sheet object to draw our arc on it. But in guild to visualize it, we demand a paint object to pass the to the drawArc canvas method. Let's create it:

          // ...          private val parentArcColor = context?.resources?.getColor(R.color.gray_light, null) ?: Color.GRAY

individual val parentArcPaint = Paint().use {
style = Pigment.Style.STROKE
isAntiAlias = true
color = parentArcColor
strokeWidth = 40f
}

// ...

The paint object arguments are self-explanatory, just a skillful matter to note is to:

Use the isAntiAlias flag to ensure your drawing has smooth edges.

And let information technology be a circle 🎨

          // ...          override fun onDraw(canvas: Canvass?) {
setSpace()
canvass?.allow {
it.drawArc(ovalSpace, 0f, 360f, fake, parentArcPaint)
}
}

In order to see anything, we need to make certain our custom view is added to the primary activity layout. The name of the custom widget will be the name of our course in this example CirculaProgressView.

                      <com.labs.circularprogress.CircularProgressView
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="200dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />

And we will be able to see:

Groundwork arc.

Drawing the inner circle 🎨

Now that we already know how to describe an arc, this part would be like shooting fish in a barrel, just declare a paint object for it and draw information technology on our onDraw method. In that location would exist a few differences, just I'll be explaining each of the ones. Let's run into:

          // ...
private val fillArcPaint = Paint().apply {
style = Pigment.Style.STROKE
isAntiAlias = true
color = fillArcColor
strokeWidth = 40f
// 1
strokeCap = Paint.Cap.ROUND
}
override fun onDraw(sheet: Sail?) {
setSpace()
canvas?.let {
// 2
drawBackgroundArc( it )
// 3
drawInnerArc( it )
}
}
private fun drawBackgroundArc(information technology: Canvas) {
it.drawArc(ovalSpace, 0f, 360f, false, parentArcPaint)
}
private fun drawInnerArc(canvas: Canvas) {
// iv
val percentageToFill = 180f
// 5
canvass.drawArc(ovalSpace, 270f, percentageToFill, fake, fillArcPaint)
}

Taking a look at the differences 🧐

  1. strokeCap = Paint.Cap.ROUND this would make the border of the stroke while drawing to look circular instead of flat.

The left arc shows a square cap and the correct a rounded one.

2. We moved the logic to draw the groundwork arc into it'south own functions to improve readability at the onDraw method.

three. Created another role that will take care of drawing the inner arc.

4. We set the canvas#drawArc sweepAngle parameter to 180f every bit right at present we only desire to depict half of the circle.

v. Here we tin notice a 270f value for our startAngle parameter, this is because the angle diagram does non start as we use to. The 270f value volition set the startAngle at the pinnacle as you could run across in the side by side image.

Android canvas bending system

Permit's start with animations 🚀

Allow'due south do a tiny recap. In order to be able to draw something, we need to specify everything that we want to bear witness at our view onDraw role. Easy peasy right? At present… if we want to brandish something new in our sheet we need to draw everything we had earlier and so describe the new affair we want it to announced, in our case this new affair would exist an incrementing arc to prove the progress.

To achieve this we need a few things:

  • A value that indicates the per centum of our arc to draw and that we tin can alter dynamically that can be read from our onDraw office
  • Draw the new value
  • And call a redraw for our view
  • And repeat

Showtime, let'due south modify our drawInnerArc role to employ a dynamic currentPercentage value to determine the per centum fill to be fatigued:

          private var currentPercentage = 0          //...          private fun drawInnerArc(canvass: Canvas) {
val percentageToFill = getCurrentPercentageToFill()
canvas.drawArc(ovalSpace, 270f, percentageToFill, false, fillArcPaint)
}
individual fun getCurrentPercentageToFill() =
(ARC_FULL_ROTATION_DEGREE * (currentPercentage / PERCENTAGE_DIVIDER)).toFloat()

To draw the new value, we have to ask the view for a redraw and this is done b calling the view invalidate() method when a redraw is needed.

Now we'll create a role to be called when nosotros want to perform the blitheness. Here we use Android'south ValueAnimatorgrade to helps united states change the the currentPercentage value through time and call our viewinvalidate() on each alter, and then it can be visualized.

The documentation defines the ValueAnimator course a a simple timing engine for running animations which calculate animated values and ready them on target objects.

In our case, we want to animate from values 0% to 100%, and this grade will make achieve this blitheness a slice of cake. So let's accept a look into the code, a, I'll explain each footstep on the go:

          fun animateProgress() {
// one
val valuesHolder = PropertyValuesHolder.ofFloat(
PERCENTAGE_VALUE_HOLDER,
0f,
100f
)

// two
val animator = ValueAnimator().apply {
setValues(valuesHolder)
duration
= 1000
interpolator = AccelerateDecelerateInterpolator()

// iii
addUpdateListener {
// 4
val percentage = information technology.getAnimatedValue(PERCENTAGE_VALUE_HOLDER) as Float

// 5
currentPercentage = percentage.toInt()

// half-dozen

invalidate()
}
}

// 7
animator.start()
}
companion object {
// ...

const val PERCENTAGE_VALUE_HOLDER = "percentage"
}
  1. We create a PropertyValuesHolder example for property the values that we want to animate. In this instance, nosotros will animate from 0 to 100 percent. In order to create this example nosotros also demand to pass a propertyName that nosotros will use later to grab the current blithe value from the animator.
  2. Hither we create an case of ValueAnimator, nosotros set the property values declared before and also pass how much fourth dimension in milliseconds we want the animation to last.
  3. This will be called on every frame of the blitheness, providing u.s.a. with the calculated per centum value for a specific frame. This value will be used to update the currentPercentage animation later.
  4. We become the current animation value (animatedValue) from our updateListener using the propertyName declared earlier.
  5. Update the currentPercentage variable that is used to describe our inner arc on each onDraw call.
  6. Now we telephone call for a view redraw after we already updated the value.
  7. We run our animation.

Annotation: This animation will start only when the function animateProgress get called.

In society to trigger our new blitheness, we'll demand to add a Button to our activeness layout in order to perform start it when clicking the button.

                      // ...                                                          <Button
android:id="@+id/animateButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="animate"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/progress" />
// ...

And add a clickListener on our Activity grade:

          animateButton.setOnClickListener            {
progress.animateProgress()
}

And there you go!

Concluding blitheness

Y'all can find the full code hither.

Hope y'all enjoyed this post, you can follow me on twitter @paulnunezm where I unremarkably tweet most Android Dev. And let please let me know what y'all call back in the annotate department bellow.

mickelsenbising.blogspot.com

Source: https://medium.com/@paulnunezm/canvas-animations-simple-circle-progress-view-on-android-8309900ab8ed

0 Response to "Draw a Circle Android Cnavas"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel