Draw a Circle Android Drawable

Did y'all ever desire to create highly-customized user interfaces in Android? Then this is the tutorial for you!

To draw custom shapes, you need to proceed iterating until you accomplish the cute art yous want. In this tutorial, you'll learn how to draw your design on newspaper first to avert wasting time via trial and error.

You'll ameliorate an app called Stars of Science. You'll larn how to create custom shapes past painting a profile card with a curved custom shape and gradient colors.

Throughout the tutorial, you'll learn how to:

  • Prepare a custom shape on newspaper before coding.
  • Extend the Android View to draw and paint it on the Canvas.
  • Draw a curved shape in slope colors.

The custom shape you'll create volition look like this:

Android custom shape

Annotation: This tutorial assumes you sympathise the nuts of Android development with Kotlin. If you're new to Android development, please go through Outset Android Development with Kotlin to sympathize the basics. If yous're new to Kotlin, check out this Introduction to Kotlin tutorial.

Getting Started

Download the project materials by clicking the Download Materials button at the superlative or bottom of this tutorial. Launch Android Studio 3.half dozen.1 or later and select Open an existing Android Studio project. Then navigate to and select the starter project folder where y'all'll find the files you lot need to showtime, along with some widgets.

Your app already has its bones UI prepare and then you tin focus on cartoon custom shapes in Android.

Build and run the app. You lot'll see the following screen on your mobile telephone or Android emulator:

The starter app showing a plain bio card

It's groovy, only the top of the card doesn't have much pizazz. You lot'll change that throughout the tutorial.

Exploring the Projection

Take a quick look at the project construction. Expand starsofscience parcel and cheque out the folders within:

Hither'due south a breakdown of the folders:

  • utils contains 4 files with extension functions you lot'll use in your painting journey.
  • view contains CircularImageView which y'all'll use to display the avatar in a circular shape. The code inside this class is out of the telescopic of this tutorial.
  • starsofscience contains 3 files:
    • MainActivity.kt is the app's primary and luncher activity.
    • Painter.kt contains pigment() which y'all'll implement to paint your custom shape. You lot'll add all drawing and painting logic to this part.
    • CustomPainter.kt is a custom Android View with a constructor accepting the width and pinnacle of your custom shape in addition to a painter object that has all the drawing and painting logic. This CustomPainter overrides onDraw() and delegates all the drawing to the painter by executing canvas?.let(painter::pigment).

Now that y'all know more than nigh the classes yous'll piece of work with take a moment to learn some of the theory behind making beautiful shapes.

Coding Your Shapes

Earlier diving into drawing with Android Canvass, yous demand to know which tools you'll need, how to use them and how to ready to code your target shape.

Remember about drawing in the physical globe. To draw a shape, you need to get a pencil and newspaper and then use your hand to move the pencil across the newspaper'southward surface. Finally, if you want to go far beautiful, you need to get a castor with some paint.

In this department, you'll starting time by drawing a shape freehand. Catch a pencil and paper and get ready!

Know Your Sail

Your canvas acts every bit the digital version of the slice of paper you lot depict on. It holds all your drawing elements, including lines, curves, arches, shapes, text and images.

The canvas needs a size, including width and summit. Drawing on a canvas without knowing its size can lead to unexpected results.

On your paper, earlier drawing any shape, define the canvass by cartoon a rectangle of any size you desire. Any shapes yous draw later volition be relative to that canvas.

Rectangle on paper

Note: Yous don't desire your shapes to have an absolute position or size. Instead, make them relative to the size of the canvas. This lets you display your shapes on different devices with different screen sizes.

For instance, you might place your shape at the center of the canvas or make its size equal to one-half of the canvas size.

At present that you accept a sheet, it's time to create a shape.

Defining How to Move Your Pencil

In visual arts, y'all have to movement your pencil properly across the paper's surface to create your artwork. You'll use the same mechanism to draw on the canvas.

Before you lot can draw a shape, yous demand to consider which functionalities the sheet object needs to take.

For case, if you desire to draw a square, you need to draw four lines. Then, yous need the drawing line function in your framework. On the other hand, if you desire to draw a crescent, you lot need to depict two curves with the drawing curve office.

Option up your pencil and depict a circumvolve in the center of the circle that'due south a quarter of the width, like this:

Draw a circle on paper

Now, to catechumen that shape on your paper into a shape in Android, you need to consider its coordinates.

Computing Coordinates

Coordinates are pairs of numbers that ascertain the verbal location of a indicate on a plane.

Earlier you lot draw anything, you need to know the main points that make up that shape. For proficient practice, calculate all the coordinates and dimensions on your paper earlier writing whatsoever lawmaking. This saves you lot coding time and makes you focus on translating that shape from the paper onto your device.

Since y'all already drew a circle relative to the canvas on your paper, you already calculated 2 things:

  1. The centre of the circumvolve: Since your circle is at the center of the canvass, the center of the circle is the center of the canvas. So the ten coordinate of the circle's center is equal to half of the width of the sheet and the y coordinate of the circle's centre is equal to half of the height of the sail. This means that:
    cx = canvass width / ii
    cy = canvas height / 2
  2. The radius: Since your circumvolve is a quarter of the sheet width, the diameter of the circumvolve is equal to a quarter of the width of the canvas. The radius is equal to one-half of the diameter. That means:
    diameter = canvas width / 4
    radius = bore / ii = canvas width / 8

Circle properties

See, drawing your shapes on paper helps you calculate the points y'all need to draw your shape relative to the sail.

It's efficient to visualize what you need to do before information technology's fourth dimension to translate your ideas into code. Making paper sketches is a prerequisite for your custom cartoon! :]

Using CustomPainter

Now that you lot've learned some theory, it's time to start using the Android Canvas and add some lawmaking that will reproduce your drawing in the app.

Implementing the Painter Interface

Start by creating a new class ProfileCardPainter in the starsofscience packet. So supervene upon the whole file content with:

package com.raywenderlich.android.starsofscience  import android.graphics.* import androidx.annotation.ColorInt  //1 course ProfileCardPainter(     //two     @ColorInt private val color: Int ) : Painter {   //three   override fun paint(canvas: Canvass) {    } }        

Hither you:

  1. Define a new class named ProfileCardPainter that implements the interface Painter.
  2. Then in its primary constructor you lot define the profile color as a class holding.
  3. Finally, y'all implement paint(canvass: Canvas). CustomPainter volition phone call this method whenever the object needs to paint.

    Yous'll write all your cartoon code inside this function, which gives you one parameter: The canvas to depict on.

Rendering With CustomPainter

Become to MainActivity.kt. You'll find the following line of code in onCreate():

profileCardContainer.setBackgroundColor(R.colour.colorPrimary.toColorInt(this))        

It sets a background color to the profileCardContainer which is a FrameLayout already defined in XML. You don't need that line anymore because you want to add your custom shape instead of that solid color.

Replace that line with the following code:

//one val azureColor = R.color.colorPrimary.toColorInt(this) val avatarRadius = R.dimen.avatar_radius.resToPx(this) val avatarMargin = R.dimen.avatar_margin.resToPx(this) val cardWidth = ViewGroup.LayoutParams.MATCH_PARENT val cardHeight = R.dimen.profile_card_height.resToPx(this).toInt() //2 val painter = ProfileCardPainter(   colour = azureColor ) //three profileCardContainer.addView(   CustomPainter(     context = this,     width = cardWidth,     height = cardHeight,     painter = painter   ) )        

Add whatever missing import by pressing Option+Enter on Mac or Alt+Enter on PC.

In the code above:

  1. You ascertain the properties of your custom shape: Color, avatar radius, avatar margin, width and height.
  2. Then, you create a ProfileCardPainter with the color yous previously divers.
  3. Finally, you add together a new CustomPainter every bit a subview of profileCardContainer by passing all its needed properties:
    • context to create this custom Android View.
    • width and height of the custom shape.
    • painter responsible for all the drawing logic.

Build and run the app to come across… a pretty ugly carte because y'all haven't fatigued annihilation nevertheless. Don't worry, you'll start drawing something in a moment. :]

Initial changes to the app

Drawing Your First Shape

In this section, yous'll practise with the tools you need to depict in the computer graphics world. They're a lot like the physical tools you used to draw a circumvolve on a newspaper. Then, with this knowledge, you'll depict your first shape!

Note: Graphics libraries have like APIs for cartoon, which makes drawing in Android comparable to drawing in iOS, Flutter and the web. When you chief drawing custom shapes on ane platform, it'south piece of cake to reuse this knowledge on other platforms.

Drawing and Painting a Rectangle

To depict a rectangle, you need to create a RectF object with the size you desire. You lot then need a Paint object with the color you adopt to start cartoon that RectF on the canvas.

RectF is a simple course with four immutable float properties: Left, top, right and bottom. These four numbers correspond a rectangle, where:

  • Left is the left-most betoken on the ten-axis.
  • Height is the top-most point on the y-axis.
  • Right is the right-most point on the x-axis.
  • Bottom is the bottom-most signal on the y-axis.

Notation: You tin calculate whatever extra properties in RectF, similar the width and height, based on these four primary properties.

In this tutorial, you lot'll rely on RectF for your shape bounds. You'll depict each shape inside of and based on a certain RectF.

In ProfileCardPainter.kt, become to paint() and add the following:

//1 val width = canvas.width.toFloat() val height = canvas.summit.toFloat() //2 val shapeBounds = RectFFactory.fromLTWH(0f, 0f, width, height) //3 val paint = Paint() paint.color = color //4 canvas.drawRect(shapeBounds, paint)        

Add together whatever missing import by pressing Option+Enter on Mac or Alt+Enter on PC.

Here's what this lawmaking defines:

  1. The width and acme of the sheet.
  2. shapeBounds is a RectF with a size that fits the whole area of the canvas by using the factory function fromLTWH().
  3. paint is your pigment and its colour.
  4. Finally, you depict your shapeBounds on the canvas by passing it to drawRect() along with your pigment from the previous line.

At present, build and run the app. See that the card now has a blue rectangle as its groundwork. Hooray, you've drawn your get-go shape! :]

The starter app showing a plain bio card

That'south amend, but at that place's still much room for comeback!

Using a Path to Draw the Contour Card

A path is non a bitmap or raster, and information technology doesn't have pixels. It's an outline that represents a series of polish lines, arcs or Bézier curves. Using a path makes your shapes scalable and contained of the screen'southward resolution.

Path is a powerful class that y'all can use in many situations. For example, you tin can clip a bitmap by a path, or you can utilize a path to draw a custom shape like you're about to do right now.

Drawing the Profile Card

In this section, y'all'll start using the Path form to draw a more complex shape like the blue shape here:

Profile card shape

But before you lot beginning, y'all need to do some preparation.

In that location are a few things you should note in the previous paradigm:

  • Blackness dashed rectangle: Represents the whole sail.
  • Red dashed rectangle: Marks the bounds of the blue shape. It has the same width and height as the canvas, except that you decrease the avatar radius from its height.
  • Blue shape: A rectangle with a half circle, an arc of a circle, equally a negative space at the lesser heart. This arc should have a radius equal to the radius of the avatar.

Annotation: An arc is a segment of a curve. In this instance, the arc you'll use is a section of a circumvolve's circumference, also called a circular arc.

The image below shows a blue arc that starts at the zero degree angle and sweeps to ninety degrees.

90 degrees arc

Outset, get the radius of the avatar. Start by calculation a new grade property called avatarRadius to your ProfileCardPainter primary constructor:

grade ProfileCardPainter(     @ColorInt private val color: Int,     individual val avatarRadius: Bladder ) : Painter {        

Then, get to MainActivity.kt and, in onCreate(), pass the avatarRadius to ProfileCardPainter:

val painter = ProfileCardPainter(   color = azureColor,   avatarRadius = avatarRadius )        

Finally, return to ProfileCardPainter.kt and update the shapeBounds by subtracting the avatarRadius from its superlative in fromLTWH():

val shapeBounds = RectFFactory.fromLTWH(0f, 0f, width, height - avatarRadius)        

The avatar radius

To see the results build and run the app:

Initial results for your custom painter

Dandy! Now the blueish background stops halfway downward the length of the avatar.

Calculation Negative Space Around the Avatar

Adjacent, yous'll add some negative space to the blue shape to set it apart from the avatar. Add together a new office called drawBackground() to ProfileCardPainter:

            private fun drawBackground(canvas: Canvas, bounds: RectF, avatarBounds: RectF) {   //ane   val paint = Paint()   paint.color = color    //2   val backgroundPath = Path().apply {     // iii     moveTo(premises.left, bounds.top)     // 4     lineTo(bounds.bottomLeft.x, premises.bottomLeft.y)     // five     lineTo(avatarBounds.centerLeft.x, avatarBounds.centerLeft.y)     // 6     arcTo(avatarBounds, -180f, 180f, fake)     // vii     lineTo(bounds.bottomRight.10, bounds.bottomRight.y)     // 8     lineTo(bounds.topRight.x, bounds.topRight.y)     // 9     close()    }    //10   canvas.drawPath(backgroundPath, paint); }        

Add any missing import by pressing Option+Enter on Mac or Alt+Enter on PC. To import all the extension functions y'all need for RectF in a row, add the post-obit import:

import com.raywenderlich.android.starsofscience.utils.*        

This diagram illustrates the proper coordinates for each signal yous need to build the path.

Custom path

In the previous code:

  1. You create a Pigment object and prepare its colour.
  2. Then, you lot create a Path object.
  3. You move to the top-left corner, P1, without cartoon a line. This is like moving a pencil to a starting betoken without touching the newspaper.
  4. Adjacent, you add a straight line that starts at P1 and ends at P2.
  5. And so, you lot add together a straight line that starts at P2 and ends at P3: The point at the edge of where you lot volition start drawing the arc.
  6. Then, starting from P3, add together an arc in the upper half region of the avatar bounds: The arc starts from the angle -180 degrees and sweeps by 180 degrees ending at P4.
    You pass simulated every bit the last parameter to forbid starting a new sub-path for the arc. This tells Android that you want the arc on the same path.
  7. Adjacent, you add a directly line that starts from the current betoken and ends at P5 at the bottom-right corner.
  8. You cease by adding a straight line that starts from the current point P5 and ends at the given point P6 at the elevation-right corner.
  9. Then y'all close the path by adding a straight line that starts at the current signal P6 and ends at the get-go point on the path, P1.
  10. Finally, you draw the backgroundPath on the canvas by passing it to drawPath() with paint.

In the previous code, you tin can collapse lines five and 6 in a unmarried line. Do you know how? You lot can find the solution in the spoiler beneath.

[spoiler title="Solution"]
You tin can collapse lines 5 and six by leaving only line 6.

arcTo(avatarBounds, -180f, 180f, imitation)

The official documentation of

arcTo(RectF oval, bladder startAngle, bladder sweepAngle, boolean forceMoveTo)

states: "If the start of the path is unlike from the path'south current last point, then an automatic lineTo() is added to connect the electric current contour to the start of the arc."
[/spoiler]

Phew! That was a lot of code, only it was worth the effort!

Creating the Rectangle Around the Avatar

In ProfileCardPainter, go to pigment() and replace the last 3 lines:

          val paint = Paint()     paint.colour = color     canvas.drawRect(shapeBounds, paint)        

with the post-obit code to create a new RectF around the avatar:

//1 val centerAvatar = PointF(shapeBounds.centerX(), shapeBounds.bottom) //2 val avatarBounds = RectFFactory.fromCircle(middle = centerAvatar, radius = avatarRadius) //3 drawBackground(canvas, shapeBounds, avatarBounds)        

Here's what this code does:

  1. Yous create a PointF object for the center point of the avatar, where 10 is the shapeBounds.centerX() and y is the bottom of the shapeBounds.
  2. Then, y'all create a RectF object from the avatar circumvolve using fromCircle(). The center is centerAvatar, which you just created, and the radius is the avatarRadius.
  3. Finally, you lot phone call drawBackground() and pass the canvas with rest of the parameters to describe your get-go path.

Build and run the app. Y'all'll see this:

Initial results for your custom painter

You probably don't discover the difference even so. Don't worry, you'll set that side by side.

Adding a Margin Effectually the Avatar

There is a difference, but you tin can't run into it because the negative infinite is exactly equal to the round avatar's size. Side by side, you'll brand that negative space a bit bigger to leave a margin between it and the avatar.

Outset, get the margin of the avatar. Beginning past calculation one more class belongings called avatarMargin to your ProfileCardPainter chief constructor, don't forget the comma at the end of the line above the new code.

class ProfileCardPainter(     ...     private val avatarMargin: Float )        

Then, go to MainActivity.kt and, in onCreate(), pass the avatarMargin to the ProfileCardPainter constructor:

val painter = ProfileCardPainter(   ...   avatarMargin = avatarMargin )        

Finally, return to ProfileCardPainter.kt and\where you create the avatarBounds in paint, add together .inflate(avatarMargin) to the end:

val avatarBounds = RectFFactory.fromCircle(middle = centerAvatar, radius = avatarRadius).inflate(avatarMargin)        

Calling inflate() on a RectF creates a new RectF object whose left, height, right and bottom edges are moved outwards by the given value. The result is a dainty space around the avatar.

To run into the margin in action, build and run the app.

Margin around the avatar

Pretty... simply ordinary. Next, you'll spice up the groundwork by adding an attractive curved shape.

Calculation More Bully Shapes

To enhance your custom shape, you can add some uncomplicated decorations like stars or circles in a partially-faded color. For this app, you'll add a more than interesting decoration: A curvy shape in gradient colors.

Adding a Curved Shape

Before you start drawing, take a moment to larn about the different types of curves. The Quadratic Bézier Curve and the Cubic Bézier Bend are two commonly used curves.

  • A quadratic Bézier curve requires three points to depict: A start point, an endpoint and a handle point that pulls the curve towards it.

    Quadratic Bézier Curve

  • A cubic Bézier bend needs iv points to draw: A start signal, an end point and two handle points that pull the curve towards them.

    Cubic Bézier Curve

Next, you'll use a quadratic Bézier curve to create an interesting groundwork shape.

Drawing a Quadratic Bézier Bend

Start past creating a new role called drawCurvedShape() inside ProfileCardPainter with the following:

private fun drawCurvedShape(canvass: Canvas, bounds: RectF, avatarBounds: RectF) {   //one   val paint = Paint()   pigment.color = color.darkerShade()    //ii   val handlePoint = PointF(bounds.left + (bounds.width() * 0.25f), bounds.top)    //3   val curvePath = Path().utilise {     //4     moveTo(bounds.bottomLeft.10, bounds.bottomLeft.y)     //5     lineTo(avatarBounds.centerLeft.x, avatarBounds.centerLeft.y)     //half dozen     arcTo(avatarBounds, -180f, 180f, false)     //vii     lineTo(premises.bottomRight.ten, premises.bottomRight.y)     //viii     lineTo(bounds.topRight.10, bounds.topRight.y)     //nine     quadTo(handlePoint.ten, handlePoint.y, bounds.bottomLeft.x, bounds.bottomLeft.y)     //10     shut()   }    //11   canvass.drawPath(curvePath, paint) }        

This diagram will help yous sympathise the code you added. Use information technology every bit a guide to the proper coordinates for each signal you'll build to create the path:

Path for new arc

In the previous code:

  1. Yous create a Paint object and set its colour to a darker shade of the profile color.
  2. Then, you create a handle point at the superlative left corner of the RectF, shifted to the right by 25% of the width of the RectF. This is P6 in the guide image.
  3. Y'all create a Path object.
  4. And then, you motility to the bottom-left corner, P1 in the guide prototype.
  5. You add a directly line that starts from P1 and ends at P2: The center point at the border of the blackness dashed avatar bounds RectF.
  6. Then, starting from the current point, P2, add an arc in the upper- half region of the avatar bounds: The arc starts from the angle -180 degrees and sweeps past 180 degrees catastrophe in P3.
    Yous pass fake as the last parameter so y'all don't start a new sub-path for the arc. This tells Android that yous want the arc on the aforementioned path.
  7. You lot add a straight line that starts from the current point and ends at the given point, the bottom-correct corner. This adds a line from P3 to P4.
  8. Then, y'all add together a directly line that starts from the current point and ends at the given bespeak, the elevation-right corner, adding a line from P4 to P5.
  9. You add a quadratic Bézier bend that starts from the electric current point, P5, and ends at the bottom-left corner, P1, using the handle point you created in step ii.
  10. Finally, you lot close the path, even though information technology's not required this fourth dimension since you are back at the get-go point on the path.
  11. Yous draw curvePath on the canvas by passing information technology to drawPath() along with the pigment object.

Finalizing the Curve

Y'all're almost finished creating the curve. In ProfileCardPainter, get to the last line in paint() and add the following code:

//1 val curvedShapeBounds = RectFFactory.fromLTRB(     shapeBounds.left,     shapeBounds.peak + shapeBounds.height() * 0.35f,     shapeBounds.correct,     shapeBounds.bottom ) //2 drawCurvedShape(canvas, curvedShapeBounds, avatarBounds)        

Here, you:

  1. Create a RectF that is similar to the shapeBounds rect, except you've shifted its acme slightly to the bottom past 35% of the shapeBounds' top: This is the crimson dashed RectF in the image higher up.
  2. Telephone call drawCurvedShape() and pass the canvass object, the curved shape bounds and the avatar bounds to information technology.

Build and run the app to see the neat background curve behind the avatar:

Add a curve behind the avatar

So you're done, correct? Almost. There's still one more finishing touch you need to add together.

Adding Slope Paint

Y'all've created your first beautiful, custom curved shape, merely your graphic designer wants you to practise one more than matter: Add together slope colors to your curved shape.

There are different types of shaders or gradients, including linear gradients, which transition through at least two colors in a directly line, and radial gradients, which transition through colors starting from a central point and radiating outward.

Correct now, y'all'll create a shader, a linear gradient described past three colors. Each color needs a cease to specify its position on a line from 0.0 to 1.0.

Start by creating a new office chosen createGradient() inside ProfileCardPainter with the post-obit code:

            individual fun createGradient(bounds: RectF): LinearGradient {   //one   val colors = intArrayOf(color.darkerShade(), color, color.darkerShade())   //2   val stops = floatArrayOf(0.0f, 0.3f, ane.0f)   //3   return LinearGradient(       bounds.centerLeft.x, premises.centerLeft.y,       bounds.centerRight.ten, premises.centerRight.y,       colors,       stops,       Shader.TileMode.REPEAT   ) }        

Hither's what'south going on in this code:

  1. You create a list of three colors, where the heart color is the profile color and the first and last colors are darker shades of that contour color.
  2. And so you lot create a list of three stops. The beginning is 0.0, which puts the corresponding color in the colors list at the zip position of the gradient colour. In the same way, the middle and the stops specify the positions of their respective colors in the color list.
  3. Finally, yous create a linear gradient by passing the start coordinates and the end coordinates of the gradient with the given colors and stops, and the shader TileMode to repeat the gradient in case the area which yous fill up is larger than the shader yous created.

Now go to drawCurvedShape() and update the paint object to use the new linear gradient instead of a solid color.

Supplant this line:

paint.color = color.darkerShade()        

With this one:

paint.shader = createGradient(bounds)        

Here, you create a new gradient and prepare it to the paint object.

Finally, build and run the app to come across a gradient within the groundwork bend:

Background curve with gradient

Congratulations! You've created a beautiful contour card with an centre-catching custom background shape and shading.

Where to Go From Here?

Y'all can download the completed concluding projection using the Download Materials button at the summit or bottom of the tutorial.

Wow, that was a lot of work! But you learned a lot, too. In addition to taking a deep wait at Canvas and many Android Graphics APIs, you learned how to:

  • Prepare your custom shape on newspaper before coding.
  • Use Path and how to add different lines to it sequentially.
  • Draw a curved shape in gradient colors.

To learn more virtually Canvas and Android custom views bank check out the following links:

  • Android Custom View Tutorial.
  • Making your drawing Interactive.
  • Custom Android Compound View.

Too, you lot can cheque RichPath library. Information technology's an open-source library that gives y'all total control over your custom shapes in vector drawable format so you lot can dispense and animate them easily at runtime.

Experience free to share your feedback, comments or enquire questions in the forum below. Don't stop cartoon. ;]

mintermaland64.blogspot.com

Source: https://www.raywenderlich.com/9556022-drawing-custom-shapes-in-android

0 Response to "Draw a Circle Android Drawable"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel