Skip to main content
  1. Posts/

Making a custom border shape in Flutter with ColorFiltered

<time datetime="2023-02-10 00:00:00 &#43;0000 UTC">10 February 2023</time><span class="px-2 text-primary-500">&middot;</span><span title="Reading time">3 mins</span><span class="px-2 text-primary-500">&middot;</span> <span class="mb-[2px]"> <a href="https://github.com/cgutierr-zgz/cgutierr-zgz.github.io/edit/main/content/posts/color-filtered-to-the-rescue/index.md" class="text-lg hover:text-primary-500" rel="noopener noreferrer" target="_blank" title=""><span class="relative inline-block align-text-bottom px-1 icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M490.3 40.4C512.2 62.27 512.2 97.73 490.3 119.6L460.3 149.7L362.3 51.72L392.4 21.66C414.3-.2135 449.7-.2135 471.6 21.66L490.3 40.4zM172.4 241.7L339.7 74.34L437.7 172.3L270.3 339.6C264.2 345.8 256.7 350.4 248.4 353.2L159.6 382.8C150.1 385.6 141.5 383.4 135 376.1C128.6 370.5 126.4 361 129.2 352.4L158.8 263.6C161.6 255.3 166.2 247.8 172.4 241.7V241.7zM192 63.1C209.7 63.1 224 78.33 224 95.1C224 113.7 209.7 127.1 192 127.1H96C78.33 127.1 64 142.3 64 159.1V416C64 433.7 78.33 448 96 448H352C369.7 448 384 433.7 384 416V319.1C384 302.3 398.3 287.1 416 287.1C433.7 287.1 448 302.3 448 319.1V416C448 469 405 512 352 512H96C42.98 512 0 469 0 416V159.1C0 106.1 42.98 63.1 96 63.1H192z"/></svg> </span> Suggest an edit</a> <a href="https://github.com/cgutierr-zgz/custom_cutoff_overlay" class="text-lg hover:text-primary-500" rel="noopener noreferrer" target="_blank"> ยท <span class="relative inline-block align-text-bottom px-1 icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg> </span> View source </a> </span>
Just a small heads up: Maybe a CustomPainter would be a better/easier solution, though ๐Ÿ˜‰.
I allways thought that creating a custom border shape in Flutter was a simple task, but I was wrong. I want to share with you the solution I found to achieve it.

Important note: I found this solution some time ago, and I’m not able to find the source of it. If you know the original author, please let me know so I can give him/her the credits!! ๐Ÿ˜„.

Why can’t we just use the border+borderradius properties? ๐Ÿค” #

This is the design my team wanted to achieve:
(This is just oversimplified version of it, but it’s enough to understand the problem)

design

Ok, this is not a super complex design, but I thought that it would be a simple task to achieve it. I mean, we just need to create a custom border shape, right?
That was my first thought when I started to work on this. I wanted to create a custom border shape for a widget, so I thought that I could just use the border and borderRadius properties of the BoxDecoration class.

return Container(
decoration: BoxDecoration(
        border: Border(
          top: BorderSide(
            color: Colors.red.withOpacity(0.5),
            width: 25,
          ),
          bottom: BorderSide(
            color: Colors.red.withOpacity(0.5),
            width: 90,
          ),
          left: BorderSide(
            color: Colors.red.withOpacity(0.5),
            width: 20,
          ),
          right: BorderSide(
            color: Colors.red.withOpacity(0.5),
            width: 20,
          ),
        ),
      ),
    );

So… this is what I got: container1

Not bad, let’s add some border radius to the container:

return Container(
// ...
  borderRadius: const BorderRadius.all(Radius.circular(6)),
// ...
);

Let’s see the result …
A borderRadius can only be given for a uniform Border.
… oh, no! ๐Ÿ˜ฑ

error

So it seems that we can’t use the border and borderRadius properties to achieve this design. ๐Ÿ˜ž

ColorFiltered at the rescue! ๐Ÿ˜Ž #

After some research, I found a solution that worked for me. I used the ColorFiltered widget to achieve it.
This widget allows us to apply a color filter to its child.
In this case, I used the BlendMode.srcOut mode to achieve the desired effect, with a Stack as a child, this Stack will have a DecoratedBox with a backgroundBlendMode of BlendMode.dstOut and a Container that will be the one that will determine the shape of the border.

    return ColorFiltered(
      colorFilter: ColorFilter.mode(
        Colors.red.withOpacity(0.5),
        BlendMode.srcOut,
      ),
      child: Stack(
        fit: StackFit.expand,
        children: [
          const DecoratedBox(
            decoration: BoxDecoration(
              color: Colors.black,
              backgroundBlendMode: BlendMode.dstOut,
            ),
          ),
          Container(
            margin: const EdgeInsets.only(
              top: 25,
              bottom: 90,
              left: 20,
              right: 20,
            ),
            decoration: const BoxDecoration(
              color: Colors.black,
              borderRadius: BorderRadius.all(Radius.circular(6)),
            ),
          ),
        ],
      ),
    );

And this is the result:

design-finished

Pretty cool, right? ๐Ÿ˜Ž

Conclusion ๐Ÿ“ #

In this post, I showed you how to use the ColorFiltered widget to create a custom border shape in Flutter.
Please, keep in mind that this is not the only way to achieve this! ๐Ÿ˜‰

I hope you enjoyed it and that you found it useful.
If you have any questions or suggestions, feel free to leave a comment below. ๐Ÿ˜„
Thanks for reading! ๐Ÿค“

The full source code for this post is available here ๐Ÿ”

References ๐Ÿ“š #

Author
Carlos Gutiรฉrrez