CustomPaint designs one below another in Flutter

Issue

I am trying to build a website using flutter and I want it’s background to have a wavy corner with a different color at one end. I need four blocks in this designs i.e. as you scroll you’ll reveal new blocks, and the height of each block should be the same as the height of the screen.

So, I thought of using CustomPaint to do it so I started to implement it but I am getting around 500 lines of error messages and it’s not working.

I’m new to flutter so I don’t know if I’ve implemented everything the way it should be implemented. I’ve shared all the code down below:

main.dart

import 'package:flutter/material.dart';

import 'blocks/block1.dart';
import 'blocks/block2.dart';
import 'blocks/block3.dart';
import 'blocks/block4.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            BlockOne(),
            //BlockTwo(),
            //BlockThree(),
            //BlockFour()
          ],
        ),
      )
    );
  }
}

block1.dart – block 2, 3 and 4 are almost similar:
Note- I’ve not added the wavy pattern in this code below because this itself is not working

import 'package:flutter/material.dart';

class BlockOne extends StatefulWidget {
  @override
  _BlockOneState createState() => _BlockOneState();
}

class _BlockOneState extends State<BlockOne> {
  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        if (constraints.maxWidth > 1024)
          return Desktop();
        else
          return Mobile();
      },
    );
  }
}

class Desktop extends StatefulWidget {
  @override
  _DesktopState createState() => _DesktopState();
}

class _DesktopState extends State<Desktop> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text('Desktop'),
    );
  }
}

class Mobile extends StatefulWidget {
  @override
  _MobileState createState() => _MobileState();
}

class _MobileState extends State<Mobile> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomPaint(
        size: const Size(double.infinity, double.infinity),
        painter: MobilePainter(),
      ),
    );
  }
}

class MobilePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final height = size.height;
    final width = size.width;
    Paint paint = Paint();
    paint.color = Colors.black;

    Path background = Path();
    background.addRect(Rect.fromLTRB(0, 0, width, height));
    canvas.drawPath(background, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return oldDelegate != this;
  }
}

Solution

Check the following. Here I am using a list view to show contents. In flutter it is important to understand the concept that constraints go down from parent to child and the size goes up from a child to parent.

Here is demo of how this can be achieved. dartpad demo

If the child doesn’t define a size then in ListView you have to define the itemExtent.

import 'package:flutter/material.dart';

// import 'blocks/block1.dart';
// import 'blocks/block2.dart';
// import 'blocks/block3.dart';
// import 'blocks/block4.dart';

void main() {
  runApp(ScrollableView());
}

class ScrollableView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: ListView(
//         child: Column(
      shrinkWrap: true,
      itemExtent: 200,
      children: <Widget>[
        BlockOne(),
        Container(
          color: Colors.black,
        ),
        BlockOne(),
        Text('Hello'),
        BlockOne(),
        Container(
          color: Colors.black,
        ),
        BlockOne(),
        //BlockTwo(),
        //BlockThree(),
        //BlockFour()
      ],
//         ),
    ));
  }
}

class BlockOne extends StatefulWidget {
  @override
  _BlockOneState createState() => _BlockOneState();
}

class _BlockOneState extends State<BlockOne> {
  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
//         if (constraints.maxWidth > 1024)
//           return Desktop();
//         else
        return Mobile();
      },
    );
  }
}

class Desktop extends StatefulWidget {
  @override
  _DesktopState createState() => _DesktopState();
}

class _DesktopState extends State<Desktop> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text('Desktop'),
    );
  }
}

class Mobile extends StatefulWidget {
  @override
  _MobileState createState() => _MobileState();
}

class _MobileState extends State<Mobile> {
  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      size: const Size(double.infinity, double.infinity),
      painter: MobilePainter(),
    );
  }
}

class MobilePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final height = size.height;
    final width = size.width;
    Paint paint = Paint();
    paint.color = Colors.green;

    Path background = Path();
    background.addRect(Rect.fromLTRB(0, 0, width, height));
    canvas.drawPath(background, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return oldDelegate != this;
  }
}

Answered By – Abhilash Chandran

Answer Checked By – David Goodson (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *