Matthew Croak A Brooklyn-based Flatiron School-alum, Matthew is a post-production assistant turned software engineer with a fruitful four years of experience. Currently, he is a JavaScript SDK engineer at Socket Mobile.

Clipping circles (and more) in Flutter

6 min read 1835

clipping circles in flutter

Table of Contents

Clipping images can allow more flexibility in terms of space occupied in the UI, image appeal, and style. Clipping also allows you to remove unnecessary parts of a picture, helping users focus on a point of interest.

For example, it’s common to see your profile picture in a circular layout on social media platforms. Is this because you uploaded a circular photo? Most often, no. You simply upload whatever photo you like and the clipping is done for you, reducing the amount of space your profile picture takes up on the site. This is particularly important for mobile apps.

In this post, I’ll cover the few ways you can circle clip (and more) images in your Flutter app. Before we use our first widget for image clipping, let’s set up our app and get an actual image to use.

Setting up the Flutter app

Create an app using flutter create circle_clipper_demo.

In your widget build body, make use of the SingleChildScrollView widget. For this widget’s child property, use the Column widget and give it a center alignment. For the Column's child, use a Widget list, which will contain a Text widget and a Center widget. See below.

SingleChildScrollView(
       child: Column(      
         mainAxisAlignment: MainAxisAlignment.center,
         children: <Widget>[
           const Text(
             "Hi! I'm Pizza!",
             style: TextStyle(fontSize: 25),
           ),
           Center(
             child: /// widget for picture,
           ),
         ],
       ),
     ),

Next, we need to add the widget used for our image. For this, we can use an Image widget.

const Image(image: AssetImage('./assets/pic.png'));

All that’s left to do now is to create an assets directory in the root of our project and find a picture we can use. I got an image from ClipArtMax. When you create the directory and add the picture to it, you need to specify your new asset in your pubspec.yaml.

# To add assets to your application, add an assets section like this:
 assets:
   - assets/

Run flutter pub get to ensure your pubspec.yaml changes are picked up, then let’s see how our app looks before any clipping.

Original Image

Now that we have our app established, let’s look at how we can clip our image by making use of ClipRRect.

We made a custom demo for .
No really. Click here to check it out.

Using ClipRRect in Flutter to clip circles

ClipRRect is a widget used specifically for clipping its child with a rounded rectangular shape inherently. We can use this one to create a circular clipping around our image. It’s relatively easy to implement, as it essentially wraps our original Image widget and applies a border radius to it.

ClipRRect(
     borderRadius: BorderRadius.circular(300.0),
     child: const Image(image: AssetImage('./assets/pic.png')),
   );

We are using the same original Image widget, but we’re wrapping it in ClipRRect and applying a border radius to round the supplied clipping. See the two images compared below.

Original Image
No clipping
Cliprrect Image
With ClipRRect

Notice that our image on the right has a round edge that cuts off (or clips) some of our original image. You can vary your level of clipping, too, by changing the border radius value. The higher the radius, the more circular it is. Easy, no?

Let’s cover the next way we can circle clip our images. We can use a widget that not only allows us to circle clip with ease but also to assign a background color to our clipped image (assuming your picture has the background removed). This widget is called CircleAvatar.

Using CircleAvatar to clip images in Flutter

CircleAvatar is a widget provided by Material. It’s a circle that represents a user. I find it particularly useful because it’s as easy to implement as ClipRRect, but it also allows for easy backgroundColor addition to your image.

CircleAvatar(
         backgroundColor: Colors.amber,
         backgroundImage: AssetImage('./assets/pic.png'),
         radius: 200.0
);

It’s similar to ClipRRect in the sense that it uses radius (called borderRadius in ClipRRect) to determine the level of circularity applied to a clipped image. It’s important to point out, however, that if you want your picture to be clipped correctly, you must assign it to the backgroundImage property and not child. If you were to apply it to child, the image would break out of the clipping. Let’s see these two examples below.

Using Child
Using child
Using Backgroundimage
Using backgroundImage

I like this widget because it works similarly to ClipRRect, allows flexibility for background color, and you can add a child if you want to include something besides the image (such as a badge or an “online” light) that is kept in a separate property from the image itself (rather than setting a Widget list to be assigned to child). In terms of syntax, I think it’s cleaner.

For example, you can use an AssetImage rather than wrapping AssetImage in an Image widget. Also, radius is just a double rather than having to be a property of BorderRadius. There is more flexibility with clipBehavior for ClipRRect, but for quick circle clipping (something that comes in handy for, say, a social media avatar) I really like CircleAvatar.

If, however, you want clipping that’s closer to an oval than a circle, this next widget is perfect for you.

Creating ovals in Flutter with ClipOval

ClipOval is a widget that clips the child to be in the shape of an oval. It’s very easy to use if you need ovular clipping. See below.

ClipOval(
         child: Image(image: AssetImage('./assets/pic.png'))
);

It’s very similar to ClipRRect without having to add a borderRadius property.

What if you don’t want a circular or ovular clipping path and instead, want to clip your image as a regular rectangle? For this, you can use ClipRect.

Using ClipRect to clip rectangles in Flutter

ClipRect can be thought of like ClipRRect, minus the rounded part (hence why it’s missing the second “R”). It applies a rectangular clipping path to a child widget without inherently applying rounded edges. It’s great when used ‌with other widgets that have a tendency to paint outside their bounds, such as Align. See below.

ClipRect(
         child: Align(
           alignment: Alignment.center,
           widthFactor: 0.8,
           heightFactor: 1.0,
           child: Image(
             image: AssetImage('./assets/pic.png')
           ),
       ),
     );

Here, we are using Align to keep our image centered and adjusting the widthFactor to be less than one. See the comparison with our original image below.

Original Image
Original image
Cliprect
ClipRect

By wrapping it in our clipper, we can create a rectangular clipping effect for our image. You can adjust the level of clipping by changing the widthFactor on the Align child.

We covered circle clipping with ClipRRect and CircleAvatar, as well as oval clipping and rectangle clipping with ClipRect. But what other shapes can we clip, and what if we want to create a more customized shape to clip our image? With our final widget of the post, we can do just that.

ClipPath in Flutter

ClipPath is a widget that allows the developer to customize their clipping shape (or path) to suit their intended effect. See the starter code below.

ClipPath(
         clipper: MyTriangle(),
         child: const Image(image: AssetImage('./assets/pic.png')),
     );

The structure is similar to our other clipping widgets, but we’re making use of an important property called clipper.

Let’s try clipping in the shape of a triangle. We can do this by creating our own clipping widget that extends the CustomClipper class. In our new clipping widget — let’s call it MyTriangle — we can define two functions.

The first is getClip, which is called whenever the custom clip needs to be updated, such as when our ClipPath widget first renders with our image. shouldReclip is called when a new instance of the clipper class is provided. For now, this function will just return false.

Our getClip, however, is the meat and potatoes of our custom clipping.

Path getClip(Size size) {
     final path = Path();
     path.moveTo(size.width/2, 0.0);
     path.lineTo(size.width, size.height);
     path.lineTo(0.0, size.height);
     path.close();
     return path;
 }

A few things are happening here. First, we instantiate the Path class. You can think of this class as a line being drawn onto the UI from point A, and, by using built-in methods (moveTo and lineTo), you can make it move to point B, to point C, to Point D, and so on.

Then, when you’re ready, you can close the path (close), which brings it back to the starting point. The function takes an inherent Size instance as an argument, which has two properties, width and height.

Size constructor
Image from the Flutter docs.

moveTo and lineTo create what are called sub-paths. moveTo starts a new subpath at a given set of coordinates (this is why it comes first in our case), and moveTo adds a straight line segment from the current point to a new provided point. Here is the order of operations for our coordinates.

  1. The first X coordinate provided is size.width/2 because this gives us the halfway through point of the width (or horizontal middle) of the image. The Y coordinate is 0.0 because it is at the top of our image. Together, this starts us at the top middle of our image – the first corner of our triangle
  2. The second X coordinate is size.width because that is the right-most point for our image. The Y coordinate is size.height because it is at the bottom of the image. Together, this gives us the bottom-right corner of our image, the second point on the triangle
  3. The third X coordinate is simply 0.0 because it is the left-most part of our image (horizontally). The Y coordinate is still size.height because we don’t want our path to move up or down yet. By keeping it the height of our image, the path drawn creates the bottom side of our triangle — and the convergence of our last coordinates forms the third and final corner of our triangle
  4. close establishes a final subpath between our last point (0.0, size.height) and our first point (size.width/2, 0.0).

Now, we just need to pass MyTriangle to the clipper property for our ClipPath widget. We should get the below result.

Original Image
Original image
Triangular Customclipper
With triangular CustomClipper

You can use ClipPath to create any sort of weird and wild shapes you can think of simply by including various coordinates for however many lineTo functions you want to execute. You can clone the code for this project from GitHub and experiment with these clipping widgets for yourself! Thanks for reading!

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.
Matthew Croak A Brooklyn-based Flatiron School-alum, Matthew is a post-production assistant turned software engineer with a fruitful four years of experience. Currently, he is a JavaScript SDK engineer at Socket Mobile.

Leave a Reply