68

I want to create a circle image where the image is fetched from the network and is also cached in Flutter.

Here is a code I found for a round image fetched from the network but the image not being cached.

new Container(
    width:80.0,
    height: 80.0,
    decoration: new BoxDecoration(
    shape: BoxShape.circle,
        image: new DecorationImage(
            image: new NetworkImage('https://pbs.twimg.com/profile_images/945853318273761280/0U40alJG_400x400.jpg'),
        ),
    ),
),

Now I found a widget for fetching, caching and presenting a image from the network

new CachedNetworkImage(imageUrl: 'https://pbs.twimg.com/profile_images/945853318273761280/0U40alJG_400x400.jpg')

But when I replace the NetworkImage widget with this CachedNetworkImage, it gives me an error saying the NetworkImage is not type image.

How can I achieve a round image that can be cached?

Edited: I tried this as suggested in the answer, but still got the same error: The argument type 'CachedNetworkImage' can't be assigned to the parameter type 'DecorationImage'.

              decoration: new BoxDecoration(
                shape: BoxShape.circle,
                image: new CachedNetworkImage(image: 
                      'https://pbs.twimg.com/profile_images/945853318273761280/0U40alJG_400x400.jpg'),
              ),

7 Answers 7

120

The CachedNetworkImage has a builder (ImageWidgetBuilder) to further customize the display of the image. Try it this way:

CachedNetworkImage(
  imageUrl: 'https://pbs.twimg.com/profile_images/945853318273761280/0U40alJG_400x400.jpg',
  imageBuilder: (context, imageProvider) => Container(
    width: 80.0,
    height: 80.0,
    decoration: BoxDecoration(
      shape: BoxShape.circle,
      image: DecorationImage(
        image: imageProvider, fit: BoxFit.cover),
    ),
  ),
  placeholder: (context, url) => CircularProgressIndicator(),
  errorWidget: (context, url, error) => Icon(Icons.error),
),

placeholder and errorWidget are widgets, which means you can put any widget in there and customize them as you wish.

Sign up to request clarification or add additional context in comments.

2 Comments

This solution will only work with a square picture, as otherwise, the CircularProgressIndicator will have the same ratio as the picture.
error widget will be not circled
41

DecorationImage takes an ImageProvider and not a widget.

There are two ways to solve this problem:

The cached_image_network provides a class that extends ImageProvider, i.e. CachedNetworkImageProvider:

Container(
  width: 80.0,
  height: 80.0,
  decoration: BoxDecoration(
    shape: BoxShape.circle,
    image: DecorationImage(
      image: CachedNetworkImageProvider('https://pbs.twimg.com/profile_images/945853318273761280/0U40alJG_400x400.jpg'),
    ),
  ),
)

You could also just omit the DecorationImage widget because the BoxDecoration will work on any widget:

Container(
  width: 80.0,
  height: 80.0,
  decoration: BoxDecoration(
    shape: BoxShape.circle,
  ),
  child: CachedNetworkImage('https://pbs.twimg.com/profile_images/945853318273761280/0U40alJG_400x400.jpg'),
)

In the latter example, I am using the regular CachedNetworkImage, which will return a widget.

6 Comments

Thank you for you answer! I tried both of your answer; the first one worked, but the latter example did not work... Still getting the same error: The argument type 'CachedNetworkImage' can't be assigned to the parameter type 'DecorationImage'.
@creativecreatormaybenot I actually did copy it the way you told me to do so as in the edit, but still did not work.
@dshukertjr Yes, screw me, I messed that up. You need to pass the CachedNetworkImage as the child to the Container. I updated that in the answer.
@creativecreatormaybenot Thanks! Everything works now!
This does not work with rectangular images. even with fit: BoxFit.cover
|
26

ClipOval widget is used to clip child widget into round shapes.

ClipOval(
  child: CachedNetworkImage(imageUrl: "https://pbs.twimg.com/profile_images/945853318273761280/0U40alJG_400x400.jpg",
   width: 80.0,
   height: 80.0,
  ),
)

10 Comments

Instead of using ClipRRect (which is basically used for rounded corners rectangle), you should probably be using ClipOval
This does not work with rectangular images even with fit: BoxFit.cover
@aytunch I would be happy to see your code if you could post it to stack overflow
How is this the accepted answer! ClipOval does not look like a perfect circle!
@SamersSalib When you have the width and height equal to each other, it will.
|
13

The combination of CircleAvatar and CachedNetworkImageProvider solves your problem. Here is an example:

CircleAvatar(
  backgroundImage: CachedNetworkImageProvider(
  'https://pbs.twimg.com/profile_images/945853318273761280/0U40alJG_400x400.jpg',
  ),
),

Comments

8

in my case this save my time , mybe you too.

CachedNetworkImage(
  imageUrl: url,
  errorWidget: (context, url, error) => Text("error"),
  imageBuilder: (context, imageProvider) => CircleAvatar(
    radius: 50,
    backgroundImage: imageProvider,
   ),
  );

Comments

3

General solution for any dimension

A Solution for pictures with any dimension and corner radius:

Container(
   width: 100,
   height: 125,
   decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(34.0),
      color: Colors.grey,
   ),
   child: ClipRRect(
      borderRadius: BorderRadius.circular(34.0),
      child: CachedNetworkImage(
         imageUrl: "url",
         fit: BoxFit.cover,
         placeholder: (context, url) => Center(
            child: SizedBox(
               width: 40.0,
               height: 40.0,
               child: new CircularProgressIndicator(),
            ),
         ),
         errorWidget: (context, url, error) => new Icon(Icons.error),
      ),
   ),
),

2 Comments

This is the perfect answer. Solves all the issues.
perfect thanks worked great
0

It will work by using a Container and ClipRRect. Here is an example:

Container(
  width: 160,
  height: 160,
    child: ClipRRect(
      borderRadius: BorderRadius.circular(80),
      child: CachedNetworkImage(
        fit: BoxFit.cover,
        imageUrl: '[YOUR URL]',
        errorWidget: (
          context,
          url,
          error,
        ) =>
          const Icon(Icons.error),
        progressIndicatorBuilder: (
          context,
          url,
          downloadProgress,
        ) =>
          Center(
            child: CircularProgressIndicator(
              value: downloadProgress.progress),
            ),
          )
      ),
    ),

The width and height of your Container widget are important and both should be the same.

I hope that will be useful for others ;-)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.