Drawing Custom Shapes With CustomPainter in Flutter
- Getting Started
- Exploring the Project
- Coding Your Shapes
- Know Your Canvas
- Defining How to Move Your Brush
- Calculating Coordinates
- Using CustomPainter
- Implementing the CustomPainter Class
- Rendering With CustomPaint
- Drawing Your First Shape
- Drawing and Painting a Rectangle
- Using a Path to Draw the Profile Card
- Drawing the Profile Card
- Adding Negative Space Around the Avatar
- Adding a Margin Around the Avatar
- Adding More Neat Shapes
- Adding a Curved Shape
- Drawing a Quadratic Bézier Curve
- Gradient Paint
- Where to Go From Here?
Did you ever wish you could be a painter? Or maybe you just want to create highly-customized user interfaces for your apps? Either way, Flutter lets you make those wishes come true.
To draw custom shapes, you need to keep iterating until you achieve the beautiful art you want. That can be painful in native iOS and Android development, because every time you make a change, even something small like changing a color, you’ll need to build and wait for some time.
With CustomPainter, Flutter gives you access to low-level graphics painting. Best of all, painting in Flutter is fast and efficient. For example, Flutter’s hot reload feature makes it easy to iterate quickly until you get exactly the look you want
In this tutorial, you’ll dip your hands in paint by improving an app called Stars of Science. You’ll learn how to create custom shapes by 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 paper before coding.
- Use CustomPainter and many Flutter painting APIs.
- Draw a curved shape in gradient colors.
The custom shape you’ll create will look like this:
Download the starter project using the Download Materials button at the top or bottom of the tutorial and unzip it. You’ll find the files you need to start working on your app, along with some widgets.
Your app already has its basic UI set up so you can focus on drawing custom shapes in Flutter.
Start Android Studio 3.5 or later with the Flutter plugin installed, then choose the Open an existing Android Studio project option. Select the starter project folder from your unzipped download.
After opening the project, click Get dependencies on the Packages get message near the top of Android Studio to pull down the project dependencies.
Before you make any changes to the starter project, press the green Run button in Android Studio to run the app. You’ll see the following screen on your mobile phone, iOS Simulator or Android emulator:
It’s not bad, but the top of the card doesn’t have much pizazz. You’ll change that over the course of the tutorial.
Exploring the Project
Take a quick look at the project structure. Expand lib and check out the folders inside:
The profile folder contains three files. The most important for this tutorial is the profile_card.dart file, which is where you’ll start coding.
- profile_page.dart: Includes the profile card and a short bio of the scientist.
- profile_card.dart: Displays the name, title, and avatar of the scientist.
- profile_model.dart: A data model with mocked data.
The lib folder also contains three files. Here’s a short description of each:
main()method and the MaterialApp widget.
- widgets.dart: A few small widgets to display some details.
- extensions.dart: A Dart extension method on the Color class, which gives you a darker shade of any color.
Now that you know more about the files you’ll work with, take a moment to learn some of the theory behind making beautiful shapes.
Coding Your Shapes
Before diving into drawing with Flutter
CustomPainter, you need to know which tools you’ll need, how to use them and how to prepare to code your target shape.
Think about drawing in the physical world. To draw a shape, you need to get a pencil and paper, then you need to use your hand to move the pencil across the paper’s surface to draw a shape. Finally, if you want to make it beautiful, you need to get a coloring brush with some colors.
In this section, you’ll start by drawing a shape freehand. Grab a pencil and paper and get ready!
Know Your Canvas
Your canvas acts as the digital version of the piece of paper you draw on. It holds all your drawing elements including lines, curves, arches, shapes, text, images and so on.
The canvas needs to have a size including a width and a height. Drawing on a canvas without knowing its size can lead to unexpected results.
Very important: You don’t want your shapes to have an absolute position or size. Instead, you want to make them responsive to the canvas’ size. This allows you to display your shapes on different devices with different screen sizes.
For instance, you might set your shape at the center of the canvas or make its size equal to half of the canvas size.
On your paper, before drawing any shape, define the canvas by drawing a rectangle of any size you want. Any shapes you draw later will be relative to that canvas.
Now that you have a canvas, you want to be able to create a shape inside of it.
Defining How to Move Your Brush
In visual arts, you need to move your brush properly across the paper’s surface to create your art. You’ll use the same mechanism to draw on the canvas.
Before you can draw a shape, you need to consider the functionalities the canvas object needs to have.
For instance, if you want to draw a square, you need to draw four lines — so you need to use the drawing line function in your framework. On the other hand, if you want to draw a crescent, you need to draw two curves — so the drawing curve function in your framework is the tool you need.
Hold your pencil again and draw a circle that fits in a quarter of the canvas’ width at the center of the canvas, like this:
Now, to convert that shape on your paper into a shape in Flutter, you need to consider its coordinates.
Coordinates are pairs of numbers that define the exact location of a point on a plane.
Before you can draw anything, you need to know the main points that make up that shape. For good practice, calculate all the coordinates on your paper before writing any code. This saves you coding time and it lets you focus on translating that shape from the paper onto your device.
Since you already drew a circle relative to the canvas on your paper, you already calculated two things:
The center of the circle:
Since your circle is at the center of the canvas, the center of the circle is the center of the canvas. So the x coordinate of the circle’s center is equal to half of the width of the canvas and the y coordinate of the circle’s center is equal to half of the height of the canvas. This means that:
cx = canvas width / 2
cy = canvas height / 2
Since your circle is a quarter of the canvas width, the diameter of the circle is equal to a quarter of the width of the canvas. As you know, the radius is equal to the half of the diameter. That means that:
diameter = canvas width / 4
radius = diameter / 2 = canvas width / 8
Now, you’ve seen that drawing your shapes on paper helps you calculate the points you need to draw your shape relative to the canvas.
This is an efficient way to understand exactly what you need to do when it’s time to translate your ideas into code. Always make paper sketches a prerequisite for your custom drawing! :]