Flutter CustomClipper with Stroke Border

2.1k Views Asked by At

I want to create a Widget with 2 container using a CustomClipper and add a line/stroke/border between them like:

enter image description here

So I want a bottom border on the red colored Container, that is in between the red and the yellow container. I am able to add the clip path with a custom clipper, but I don't know how can I add a line in between these two container.

My current widget is:

Container(
      margin: const EdgeInsetsDirectional.only(end: 8),
      child: ClipRRect(
        borderRadius: BorderRadius.circular(6),
        child: Stack(
          children: [
            Align(
              alignment: AlignmentDirectional.bottomCenter,
              child: Container(
                decoration: BoxDecoration(
                    color: Colors.yellow, border: Border.all(color: AppColors.instance.color0B0B0B, width: 1), borderRadius: const BorderRadius.all(Radius.circular(6))),
                height: 200,
                child: const Center(
                  child: Text("Hello"),
                ),
              ),
            ),
            Align(
              alignment: AlignmentDirectional.topCenter,
              child: ClipPath(
                clipper: MyClipper(),
                child: Container(
                  decoration: BoxDecoration(
                      color: Colors.red, border: Border.all(color: AppColors.instance.color0B0B0B, width: 1), borderRadius: const BorderRadius.all(Radius.circular(6))),
                  height: 200,
                  child: const Center(
                    child: Text("Hello Hello"),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    )

and the custom clipper class is:

class MyClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    int curveHeight = 60;
    Offset controlPoint = Offset(size.width / 2, size.height + curveHeight);
    Offset endPoint = Offset(size.width, size.height - curveHeight);

    Path path = Path()
      ..lineTo(0, size.height - curveHeight)
      ..quadraticBezierTo(controlPoint.dx, controlPoint.dy, endPoint.dx, endPoint.dy)
      ..lineTo(size.width, 0)
      ..close();

    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}

If somebody have any other good idea, please correct me. Thanks in advance!

2

There are 2 best solutions below

8
On

You can include another ClipPath on same position as red container with increasing its height a little but up.

height: 200 + 5, // main height + border

   body: LayoutBuilder(
        builder: (context, constraints) {
          return Center(
            child: Container(
              height: constraints.maxHeight,
              margin: const EdgeInsetsDirectional.only(end: 8),
              child: ClipRRect(
                borderRadius: BorderRadius.circular(6),
                child: Stack(
                  children: [
                    Align(
                      alignment: AlignmentDirectional.bottomCenter,
                      child: Container(
                        decoration: BoxDecoration(
                            color: Colors.yellow,
                            border: Border.all(
                                // color: AppColors.instance.color0B0B0B,
                                width: 1),
                            borderRadius:
                                const BorderRadius.all(Radius.circular(6))),
                        height: constraints.maxHeight / 2,
                        child: const Center(
                          child: Text("Hello"),
                        ),
                      ),
                    ),

                    ///border color
                    Align(
                      alignment: AlignmentDirectional.topCenter,
                      child: ClipPath(
                        clipper: MyClipper(),
                        child: Container(
                          decoration: BoxDecoration(
                              color: Color.fromARGB(255, 38, 240, 16),
                              borderRadius:
                                  const BorderRadius.all(Radius.circular(6))),
                          height: constraints.maxHeight * .65 +
                              5, //  main height + border
                        ),
                      ),
                    ),
                    Align(
                      alignment: AlignmentDirectional.topCenter,
                      child: ClipPath(
                        clipper: MyClipper(),
                        child: Container(
                          decoration: const BoxDecoration(
                            color: Colors.red,
                            borderRadius: BorderRadius.all(
                              Radius.circular(6),
                            ),
                          ),
                          height: constraints.maxHeight * .65,
                          child: const Center(
                            child: Text("Hello Hello"),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          );
        },
      ),

enter image description here

It will still show blank space while using MyClipper while heigt<400(around)

0
On

You can use the CustomPainter class. There, you can specify strokeWidth and Color, and then make sure you give it the same path as your above curve.