Flutter: Analog clock coding with CustomPaint

Ouzani Abd Raouf
FlutterWorld
Published in
4 min readSep 8, 2020

Flutter came with a lot of widgets in his pockets. Buttons, icons, containers, and many other widgets that are very easy to include in your code to get a beautifully designed app. But sometimes you wish to create a very, very custom user interface. In that case, the CustomPaint widget is your best choice. With this widget, you have access to low-level paint calls. These are fast and efficient, and let you build slick graphics. For example, the Material ink ripple effect is implemented using a circle.

So all you have to do is to add a CustomPaint widget to your widget tree. Give it a size (optional) and a painter. Then implement your painter. It’s a class that extends CustomPainter and implements two methods: paint and shouldRepaint.

The CustomPaint widget uses the painter to paint on the current canvas, then it paints its child. The should repaint method is called when the CustomPainter is rebuilt. You can tell the framework to reuse the previous result of paint.

CustomPaint(
painter: MyPainter(),
child: Center(
child: Text('Paint behind me !',
style: const TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
),
)

The paint method is where you get your canvas, and is free to draw.

So, let’s draw a rectangle :

class MyPainter extends CustomPainter {  @override
void paint(Canvas canvas, Size size) {
var paint = Paint()
..color = Colors.blue
..style = PaintingStyle.fill;
//Draw a rectangle
canvas.drawRect(Offset(150, 100) & Size(200, 150), paint);
}

@override
bool shouldRepaint(MyPainter oldDelegate) => false;

}

We have given to the rectangle an offset of (150, 100). The top-left coordinates of the rectangle are (150, 100). The top left corner of the canvas has an offset of (0, 0). The rectangle has a size of (200, 150). 200 is the width and 150 is the height.

The rectangle is rendered onto the canvas using the paint defined by this object. You may change the stroke color, the fill color and style, and many other properties using this paint object.

If we don’t expect any changes we can return false in the should repaint method.

You can draw lines, rectangles, circles, arcs, paths, bitmap images, and even paragraphs of text. And you have full control over how to paint these colors, shaders, blend modes, and more.

Enough talking and let’s start with our analog clock. Here is the home screen code :

Nothing special. Now we will create our FlutterAnalogClock statefulWidget:

In the initState method, we get the current time value and store it in the _dateTime variable, then we create a timer that executes an anonymous function every second. In this function, we increment the _dateTime value by one second and execute the setState method to trigger the clock repaint. This is what makes the clock animated.

Next, we will create the painter FlutterAnalogClockPainter which has as parameters the _dateTime and the _borderWidth:

In this class, we are mainly using the current _dateTime value and the mathematical formula of rotation to draw the three clock hands using different lengths and strokes width.

When the canvas “should repaint”? If there is a change in the border width of the clock or in the _dateTime value which happens every one second.

The full source code is here.

You can go further by customizing the sizes and the colors of the different parts of the clock. If you want more analog clocks for flutter, check here.

Thank you for reading this article. Please, if you like it, share it.

See also:

--

--