flutter: custom shape as text background

333

One way to achieve this is like so.

class TriangleClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    final w = size.width;
    final h = size.height;
    final triangleWidth = 10;

    final path = Path();
    path.lineTo(0, 0);
    path.lineTo(0, h);
    path.lineTo(w, h);
    path.lineTo(w - triangleWidth, 0);
    path.close();
    return path;
  }

  @override
  bool shouldReclip(TriangleClipper oldClipper) => false;
}

and use it like so.

ClipPath(
    clipper: TriangleClipper(),
    child: Container(
      padding: EdgeInsets.fromLTRB(4, 4, 14, 4),   // 4 + triangleWidth for right padding
      color: Colors.orange,
      child: Text('A label'),
    ),
),
Share:
333
jack_the_beast
Author by

jack_the_beast

Updated on December 28, 2022

Comments

  • jack_the_beast
    jack_the_beast over 1 year

    I need to achieve this in flutter:

    enter image description here

    I tried making a Row and setting a background to the Text to handle the ractangle, then a ClipPath to make the triangle. The problem with this is that the edge is not precise (you can see a thin line between the rectangle and the triangle in the image below), also the ClipPath has fixed size so if I want to change the text size at some point I'll have to fine-tune the triangle again.

    enter image description here

    here's my code:

    class TriangleClipper extends CustomClipper<Path> {
      @override
      Path getClip(Size size) {
        final path = Path();
        path.lineTo(0.0, size.height);
        path.lineTo(size.width / 3, size.height);
        path.close();
        return path;
      }
    
      @override
      bool shouldReclip(TriangleClipper oldClipper) => false;
    }
    
    Row(
            children: [
              Container(
                color: Colors.orange,
                child: Padding(
                  padding: const EdgeInsets.all(4.0),
                  child: Text(
                    "a label",
                  ),
                ),
              ),
              ClipPath(
                clipper: TriangleClipper(),
                child: Container(
                  color: Colors.orange,
                  height: 23,
                  width: 20,
                ),
              )
            ],
          )
    

    I though using double.infinity instead of fixed size in ClipPath's child would solve it but doing that makes the triangle disappear (probably it becomes too big that I can't see it or goes behind something).

    What is the correct way to approache this problem? I guess I could draw the trapezoid using a ClipPath, but how to make it so the width of it adapts to the lenght of the Text?