Brushing Up Your Flutter Skills: Custom Painting Essentials

A Step-by-Step Guide to Painting and Drawing in Flutter

ยท

5 min read

Brushing Up Your Flutter Skills: Custom Painting Essentials

Introduction

Welcome to the colourful world of Flutter custom painting! In this guide, we will embark on an exciting journey to unlock the true potential of Flutter's CustomPainter. If you've ever wanted to create unique, visually stunning, and interactive elements in your Flutter apps, you're in the right place. Flutter, with its versatile toolkit, caters to many UI requirements, but there comes a point where you need to break free from the constraints of standard widgets. This is where the magic of Custom Painter in Flutter unfolds. Custom Painter is not just an option; it's a necessity for those seeking to craft one-of-a-kind, visually captivating, and interactive user interfaces.

Custom Painter

At its core, a Custom Painter in Flutter is a canvas on which you, as a developer, become an artist. It's a versatile tool that allows you to draw, paint, and craft your user interface elements. Think of it as a blank sheet of digital paper, ready for your creative strokes. With Custom Painter, you have complete control over how things look, from simple shapes and lines to intricate graphics. Custom Painter empowers you to design and draw UI elements that standard widgets can't match. It's a must-know skill for any Flutter developer looking to elevate their app's visual appeal and interactivity.

Canvas

An Offset represents a 2D point in space, usually expressed in terms of coordinates, where (0, 0) typically represents the top-left corner of the canvas. Flutter uses a Cartesian coordinate system, where the top-left corner of the canvas is (0, 0), and the x-axis extends horizontally to the right, while the y-axis extends vertically downward. Positive x-values move to the right, and positive y-values move downward. Offset can also be used to move a point or a shape on the canvas. By applying an Offset to an existing point, you can shift it to a new location.

CustomPaint Widget

The CustomPaint widget in Flutter is a versatile container for custom graphics and drawings. It takes a CustomPainter as a parameter, allowing developers to define their rendering logic. With CustomPaint, you can create complex custom UI elements, charts, diagrams, or any visual content by painting directly on the canvas, giving you full control over the appearance and interactivity of your app's components.

Rectangle

class MyCustomPainter extends StatelessWidget {
  const MyCustomPainter({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Flutter Custom Painter"),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        padding: const EdgeInsets.all(10),
        child: CustomPaint(
          painter: QuadrantPainter(),
        ),
      ),
    );
  }
}

class ShapePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.fill;

    final center = Offset(size.width / 2, size.height / 2);
    const rectWidth = 100.0;
    const rectHeight = 100.0;

    final rect = Rect.fromCenter(
      center: center,
      width: rectWidth,
      height: rectHeight,
    );

    final path = Path()..addRect(rect);

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}

PaintingStyle: PaintingStyle is an enum in Flutter used to define how shapes or paths are painted on the canvas. It has two values: PaintingStyle.fill and PaintingStyle.stroke

Rect.fromCenter(): Rect.fromCenter is a constructor in Flutter that creates a rectangle with a specified width and height, centered at a given Offset point.

Path(): Path is a class in Flutter used to define a series of drawing commands for custom shapes, lines, and curves.

canvas.drawPath(): canvas.drawPath is a method in Flutter's Canvas class. It is used to render the specified path onto the canvas. This is how you draw custom shapes or paths defined using the Path class.

shouldRepaint(): This method determines whether the custom painter should repaint or not. It takes an old delegate and returns a boolean. If it returns true, the painter is repainted; if false, it is not.

Circle

class ShapePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0;

    final center = Offset(size.width / 2, size.height / 2);
    const radius = 50.0;

    canvas.drawCircle(center, radius, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}

The .drawCircle method is used in Flutter's custom painting to draw a circle on the canvas. It takes three parameters: centre, radius and a paint object.

Quadrant

class QuadrantPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    const gradient = LinearGradient(
      colors: [Color(0xffBA5370), Color(0xffF4E2D8)],
      begin: Alignment.bottomCenter,
      end: Alignment.topRight,
    );

    Paint paint = Paint()
      ..color = Colors.blue
      ..shader =
          gradient.createShader(Rect.fromLTWH(0, 0, size.width, size.height))
      ..style = PaintingStyle.fill;
    Offset center = const Offset(0, 0);
    double radius = size.width / 2;

    Path path = Path();
    path.moveTo(center.dx, center.dy);
    path.lineTo(center.dx + radius, center.dy);
    path.lineTo(center.dx, center.dy + radius);
    path.arcTo(
      Rect.fromCircle(center: center, radius: size.width / 2),
      0,
      pi / 2,
      true,
    );
    path.close();
    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}

moveTo: .moveTo(dx, dy) is a method in the Path class that is used to set the starting point of a path. It moves the "pen" to the specified coordinates (dx, dy) without drawing a line.

lineTo: .lineTo(dx, dy)is another method in the Path class. It draws a straight line from the current point (where the "pen" is) to the specified coordinates (dx, dy). It creates a line segment between the current point and the new point.

arcTo: .arcTo(Rect rect, double startAngle, double sweepAngle, bool forceMoveTo) is a method in the Path class used to add an arc to the path. It's particularly useful for drawing parts of circles or curved shapes.

Rect rect: The bounding rectangle that defines the position and size of the arc. double startAngle: The starting angle of the arc in radians. double sweepAngle: The angle to sweep in radians (positive for clockwise, negative for counterclockwise).

bool forceMoveTo: If set to true, it moves the "pen" to the starting point of the arc without drawing a line, ensuring that the arc is not connected to the previous path.

Congratulations on reaching the end of this blog! I encourage you to keep experimenting with Custom Painter in Flutter. The world of custom graphics and visual storytelling is at your fingertips. Embrace your creativity, explore, and craft unique user interfaces that captivate your audience.

Happy Fluttering ๐Ÿ’™๐Ÿ’™๐Ÿ’™

Did you find this article valuable?

Support Pranav by becoming a sponsor. Any amount is appreciated!

ย