Flutter Custom Paint | Learn How to Use Custom Painter

Custom Painter helps you draw custom shape. It's relatively easy to draw custom path and shape.

In general you want to return a widget to Container() widget. What I mean by this is that, you should wrap your custom painter widget inside Container() widget.

Look at the code section below

Container(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        decoration: BoxDecoration(
          color:  Theme.of(context).primaryColor,
        ),
        child: CustomPaint(
          painter: BackgroundPainter(),
        ),
      )

See how we returned BackgroundPainter() inside CustomPaint()

Our class BackgroundPainter() extends CustomPainter() class 

If you extend CustomPainter class you need to override paint() and shouldRepaint() method.

paint() method does the actual drawing. Inside this method we create object from Paint() class. Paint() class object takes color for painting.

There's another class we need to use that's Path(). This Path() class takes the number of points to draw. If you wanna draw a triangle then use three points and if you wanna draw a rectangle like object then use four points and use the methods like moveTo() and lineTo()

See the paint() method

  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()..color = Colors.white.withOpacity(0.1);
    final path = Path();

    path.moveTo(0, 0);
    path.lineTo(size.width * 0.2, 0);
    path.lineTo(0, size.height * 0.4);
    path.close();

    final path2 = Path();

    path2.moveTo(size.width, 0);
    path2.lineTo(size.width * 0.8, 0);
    path2.lineTo(size.width * 0.2, size.height);
    path2.lineTo(size.width, size.height);
    path2.close();

    canvas.drawPath(path, paint);
    canvas.drawPath(path2, paint);
  }

At the end we pass paint and path object to canvas. We call drawPath() to do the actual drawing.

One thing we must do, we must call close() function from the path object.

The complete code

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,

        theme: ThemeData(
          primarySwatch: Colors.indigo,
        ),
        home: const HomePage());
  }
}

// Home Page
class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(

      body: Container(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        decoration: BoxDecoration(
          color:  Theme.of(context).primaryColor,
        ),
        child: CustomPaint(
          painter: BackgroundPainter(),
        ),
      ),
    );
  }
}


class BackgroundPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()..color = Colors.white.withOpacity(0.1);
    final path = Path();

    path.moveTo(0, 0);
    path.lineTo(size.width * 0.2, 0);
    path.lineTo(0, size.height * 0.4);
    path.close();

    final path2 = Path();

    path2.moveTo(size.width, 0);
    path2.lineTo(size.width * 0.8, 0);
    path2.lineTo(size.width * 0.2, size.height);
    path2.lineTo(size.width, size.height);
    path2.close();

    canvas.drawPath(path, paint);
    canvas.drawPath(path2, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return false;
  }

}

Recent posts