flutterclipping

Flutter clip without space around the clipped widget


I want to clip a widget and use this clipped image in a layout and the bounderies should be the visible part of the imgage when clipped.

Using this custom clipper

  @override
  Rect getClip(Size size) {
    Rect rect = Rect.fromLTRB(25,0,size.width - 25, size.height);
    return rect;
  }
  @override
  bool shouldReclip(CustomRect oldClipper) {
    return true;
  }
}

results in 25 px blank space left of the clipped image and 25 px blank space right of the clipped image.

enter image description here

And at least we ant to copy specific areas of an image and scale/position it exactly in the app... -> more complex desired result:

enter image description here


Solution

  • You need to add a transform to translate the widget over to the newly empty space. Just be aware that the widget itself will still occupy the same width in this example - so if there is some sibling in a row, for example, it will still get "pushed over" by the same amount of space. If you need to change that you'll need to add a SizedBox to the final part of this example so that you can trim down the size of the widget to the portion you've clipped.

    Also note that this is not a very good practice - ideally you should be fetching the image you actually want to display. Flutter will still need to load your entire image into memory and then do some non-trivial work to add the clip you want. That takes up plenty of extra CPU and memory. But sometimes you don't have a choice I guess.

    This example shows just displaying an image, followed by applying a custom clip, followed by applying a translation, which is what OP is looking for.

    import 'package:flutter/material.dart';
    import 'package:vector_math/vector_math_64.dart';
    
    void main() {
      final Widget image = Image.network(
          'https://via.placeholder.com/300x60?text=This is just a placeholder');
      const double widthAmount = 100;
      runApp(MaterialApp(
        home: Scaffold(
          body: Center(
            child: Column(
              children: <Widget>[
                Spacer(),
                image,
                Spacer(),
                ClipRect(
                  clipper: CustomRect(widthAmount),
                  child: image,
                ),
                Spacer(),
                Transform(
                  transform: Matrix4.translation(Vector3(-widthAmount, 0.0, 0.0)),
                  child: ClipRect(
                    clipper: CustomRect(widthAmount),
                    child: image,
                  ),
                ),
                Spacer(),
              ],
            ),
          ),
        ),
      ));
    }
    
    class CustomRect extends CustomClipper<Rect> {
      CustomRect(this.widthAmount);
    
      final double widthAmount;
    
      @override
      Rect getClip(Size size) {
        Rect rect =
            Rect.fromLTRB(widthAmount, 0, size.width - widthAmount, size.height);
        return rect;
      }
    
      @override
      bool shouldReclip(CustomRect oldClipper) {
        return oldClipper.widthAmount != widthAmount;
      }
    }
    

    enter image description here