Search code examples
flutterdartclipper

Insert an image into a complex shape (Flutter)


What is the best tool to use here? In my application, I will have to create banners, the data of which I will receive from the server. The data is text and an image. The difficulty is that I need to somehow make this picture such a complex shape. And so far I have not found a suitable tool to do this. I have a layout in Figma, where this form is in the vector, but I still don’t understand how to transfer it to the application and fill the picture with it. Yes, and in addition to the picture itself, there is such a form and a container where the text is (the left part is clear how to do it, with the help of Border.only(...), but I don’t understand the left part either) Thanks

enter image description here


Solution

  • You can use CustomClipper like this:

    class CustomDraw2 extends CustomClipper<Path> {
      final double radius;
      CustomDraw2(this.radius);
      @override
      Path getClip(Size size) {
        var path = Path();
    
        path.moveTo(0, 0);
        path.lineTo(size.width, 0);
        path.cubicTo(size.width - radius * 0.2, 0, size.width - radius,
            (3 * size.height / 5), size.width - radius, size.height);
        path.lineTo(0, size.height);
        path.lineTo(0, 0);
    
        path.close();
        return path;
      }
    
      @override
      bool shouldReclip(CustomClipper<Path> oldClipper) {
        return false;
      }
    }
    
    class CustomDraw3 extends CustomClipper<Path> {
      final double radius;
      CustomDraw3(this.radius);
      @override
      Path getClip(Size size) {
        var path = Path();
    
        path.moveTo(radius, 0);
        path.lineTo(size.width, 0);
        path.lineTo(size.width, size.height);
        path.lineTo(radius / 2.5, size.height);
        path.cubicTo(radius / 2.5, size.height, -radius / 2.5,
            (3 * size.height / 5), radius, 0);
    
        path.close();
        return path;
      }
    
      @override
      bool shouldReclip(CustomClipper<Path> oldClipper) {
        return false;
      }
    }
    

    and use these CustomClipper like this:

    Container(
        clipBehavior: Clip.antiAlias,
        decoration:
            BoxDecoration(borderRadius: BorderRadius.circular(16)),
        width: double.infinity,
        height: 100,
        child: LayoutBuilder(builder: (context, constraints) {
          double imageWidth = constraints.maxWidth * 0.3;
          var radius = imageWidth * 0.25;
          return Stack(
            children: [
              Positioned(
                right: 0,
                top: 0,
                bottom: 0,
                child: ClipPath(
                  clipBehavior: Clip.antiAlias,
                  clipper: CustomDraw3(radius),
                  child: Image.asset(
                    'assets/images/test.jpeg',
                    fit: BoxFit.cover,
                    width: imageWidth,
                    height: 100,
                  ),
                ),
              ),
              Positioned(
                left: 0,
                top: 0,
                bottom: 0,
                child: Container(
                  clipBehavior: Clip.none,
                  height: 100,
                  width: constraints.maxWidth * 0.76,
                  child: ClipPath(
                    clipBehavior: Clip.antiAlias,
                    clipper: CustomDraw2(radius),
                    child: Container(
                      padding: EdgeInsets.symmetric(horizontal: 12),
                      color: Colors.white,
                      alignment: Alignment.centerLeft,
                      child: Text('some text'),
                    ),
                  ),
                ),
              ),
            ],
          );
        }),
      )
    

    enter image description here