Flutter Network Image does not fit in Circular Avatar
Asked Answered
E

26

138

I am trying to retrieve bunch of images from an api. I want the images to be displayed in Circular form so I am using CircleAvatar Widget, but I keep getting images in square format. Here is a screenshot of images

enter image description here

Here is the code I am using

ListTile(leading: CircleAvatar(child: Image.network("${snapshot.data.hitsList[index].previewUrl}",fit: BoxFit.scaleDown,)),),

I tryied using all the properties of BoxFit like cover, contain,fitWidth,fitHeight etc but none of them works.

Eran answered 28/11, 2018 at 6:33 Comment(1)
Have you tried fit: BoxFit.cover?Triquetrous
H
274

This Will Work : You need to use backgroundImage:property in order to fit it in Circle.

CircleAvatar(
                radius: 30.0,
                backgroundImage:
                    NetworkImage("${snapshot.data.hitsList[index].previewUrl}"),
                backgroundColor: Colors.transparent,
              )

To Check with Dummy Placeholder:

CircleAvatar(
                radius: 30.0,
                backgroundImage:
                    NetworkImage('https://via.placeholder.com/150'),
                backgroundColor: Colors.transparent,
              )
Hochheimer answered 28/11, 2018 at 7:13 Comment(3)
and what about an image from storage, Image.file(Image.file(File file)). Can CircleAvatar handle it?Trepidation
@Trepidation yes. You can use AssetImage in backgroundImage property.Teleutospore
Sometimes you will want to use this with FadeInImage like myself...in which case the best way to do it is wrapping it in a ClipOval widget...here is a snippet: CircleAvatar( backgroundColor: Colors.grey, child: ClipOval( child: FadeInImage.assetNetwork( placeholder: placeholderPath, image: imageUrl, ), ), );Cibis
A
107

Had a similar problem in the AppBar actions widget list.

This worked for me:

CircleAvatar(
    radius: 18,
    child: ClipOval(
        child: Image.network(
          'image-url',
        ),
    ),
),
Anamorphism answered 22/1, 2019 at 12:9 Comment(0)
W
52

If you don't want to use CircleAvatar, here is how you can do it.

ClipOval(
  child: Image.network(
    'https://via.placeholder.com/150',
    width: 100,
    height: 100,
    fit: BoxFit.cover,
  ),
),
Waxwing answered 8/4, 2019 at 14:32 Comment(4)
why someone wouldn't try circle avatarGrandmotherly
@AsbahRiyas because image doesnt fill the available space. Try to use big image in very small Circle Avatar then you will know what's the problem is.Bulb
A reason for me to not use the CircleAvatar, was that it animates the background colors, which I didn't want. In other words, this solution is perfect for me, thanks.Isla
Nice worked fineWheaten
F
23

if someone intends to create bordered circular image try this.

Using ClipOval widget is not perfect solution because if images are not square result will be elliptic.

CircleAvatar(radius: (52),
            backgroundColor: Colors.white,
            child: ClipRRect(
              borderRadius:BorderRadius.circular(50),
              child: Image.asset("assets/pictures/profile.png"),
            )
        )

ClipRRect widget prevents image to overflow CircleAvatar widget.

Fushih answered 23/4, 2020 at 21:51 Comment(2)
Actually the most perfect implementation. Works fine for all image sizes and doesn't warp the image in any way. ThanksLithuanian
Don't use Clips unless necessary, which in this case it isn't. Clips can be more expensive than changing the border radius directly: flutter.dev/docs/perf/rendering/best-practicesBizet
G
14

simply use backgroundImage inside CircleAvatar

 CircleAvatar(
      backgroundImage: AssetImage("assets/images/dia.jpg",),
    ),
Gizela answered 6/11, 2020 at 22:27 Comment(1)
This isn't working for network images for me, any idea why?Legitimist
B
13

You will need to use NetworkImage, AssetImage, FileImage, MemoryImage or something similar. You can't directly use Image.network, Image.asset or similar due to how Flutter architects its image classes.

An example:

CircleAvatar(
  radius: 100.0,
  backgroundImage: NetworkImage(...),
)

backgroundImage in CircleAvatar expects to receive an ImageProvider as a parameter. However, Image.network and others don't directly extend the ImageProvider class, they merely extend the StatefulWidget class, even though they use NetworkImage inside. That is why you see in the other answers that ClipOval or ClipRRect is being used. These classes accept a Widget and so they're not as particular as CircleAvatar and similar classes are.

Instead of these workarounds, therefore, for CircleAvatar, you should use NetworkImage and similar classes and for widgets that expect just a Widget, you can use Image.network and similar.

Another reason not to use clips is that they can be more expensive than changing the border radii directly: https://flutter.dev/docs/perf/rendering/best-practices

Bizet answered 15/4, 2020 at 16:38 Comment(0)
S
7

If anyone is trying to fit a circular image in app bar actions. Try below solution it should work.

         Padding(
            padding: const EdgeInsets.all(8.0),
            child: AspectRatio(
              aspectRatio: 1,
              child: CircleAvatar(
                backgroundImage: NetworkImage('https://picsum.photos/seed/picsum/200/500'),

              ),
            ),
          )

AspectRatio first tries the largest width permitted by the layout constraints(here the appbar). If I remove the padding image radius will be of appbar size. So add padding to control the size of circular image.

Sharpset answered 4/11, 2020 at 11:24 Comment(1)
Exactly the solution is. Thanks for sharing.Dissolvent
H
6

this work for me

   CircleAvatar(
                  child:  ClipRRect(
                      borderRadius: new BorderRadius.circular(100.0),
                      child:Image.network("http://www.rd.com/wp-content/uploads/2017/09/01-shutterstock_476340928-Irina-Bg-1024x683.jpg"),
                ),),
Hannover answered 12/1, 2020 at 17:18 Comment(0)
T
6
 CircleAvatar(
        radius: 26,
        backgroundColor: Colors.white,
        child: ClipOval(
          child: _bytesImage == null
              ? new Text('No image value.')
              : Image.memory(
                  _bytesImage,
                  width: 60,
                  height: 60,
                  fit: BoxFit.cover,
                ),
        ),
      ),
Tang answered 30/6, 2020 at 10:45 Comment(0)
R
6

Wrap your CircleAvatar widget under Stack widget.

 return Stack(
      children: [
        CircleAvatar(
          radius: 50.0,
          backgroundImage: NetworkImage(
              'https://i.pinimg.com/474x/0c/eb/c3/0cebc3e2a01fe5abcff9f68e9d2a06e4.jpg'),
        ),
      ],
    );
Radiotherapy answered 8/12, 2020 at 16:30 Comment(0)
A
4

I had the same problem

CircleAvatar(
             radius: 30.0,
             backgroundImage: NetworkImage(imageURL),
             backgroundColor: Colors.transparent,
             ));

fixed my issue.

Antennule answered 7/12, 2019 at 13:42 Comment(0)
E
3

Here is a round picture with a shadow:

child: AspectRatio(
    aspectRatio: 1/1,
    child: Container(
        margin: EdgeInsets.all(
            10.0
        ),
        decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(100.0),
            boxShadow:[
              BoxShadow(
                  color: Color.fromARGB(60, 0, 0, 0),
                  blurRadius: 5.0,
                  offset: Offset(5.0, 5.0)
              )
            ],
            image: DecorationImage(
                fit: BoxFit.cover,
                image: NetworkImage(user.image)
            )
        )
    )
)
Erebus answered 30/5, 2019 at 8:53 Comment(0)
P
2
  ClipOval(
     child: Image.asset(
      'assets/dummy.jpg',
       fit: BoxFit.contain,
       matchTextDirection: true,
       height: 50,
   ))
Platinotype answered 16/8, 2019 at 4:37 Comment(1)
While this code may/may no solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations.Ranaerancagua
S
2

Use combination of width/height, fit and wrap image in ClipOval like below:

CircleAvatar(
    child: ClipOval(
        child: Image.network(
            _photo,
            width: 120,
            fit: BoxFit.fill
        ),
    ),
    radius: 50,
),
Sweet answered 31/8, 2019 at 18:39 Comment(0)
T
1

If you want to show your image covering whole width of circle avatar then you can use it like this way. And if your image didnot load then it will show default person icon.

 CircleAvatar(
              child: ClipOval(
                                  child: Center(
                                child: _image == null
                                    ? Icon(
                                        Icons.person,
                                        color: Colors.grey.shade700,
                                        size: 100,
                                      )
                                    : Image.file(
                                        _image,
                                        fit: BoxFit.cover,
                                        width: MediaQuery.of(context).size.width,
                                      ),
                              ),
                            ),

                          radius: 50,
                          backgroundColor: Colors.grey.shade300,
                        ),
Trilateration answered 21/1, 2020 at 9:32 Comment(0)
P
1

I had the same problem. Using clipoval in circle avatar will make it elliptical. But this fixed this issue.

CircleAvatar(

             radius:25.0,

             backgroundImage: NetworkImage(
                        '${image_url}',


                        ),
                        backgroundColor: Colors.blue,
                            ),   

Palmette answered 15/5, 2020 at 8:14 Comment(0)
H
1
                    CachedNetworkImage(
                        placeholder: (context, url) => Center(
                              child: CircularProgressIndicator(),
                            ),
                        errorWidget: (context, url, error) =>
                            new Icon(Icons.error),
                        imageBuilder: (context, imageProvider) => Container(
                            width: 60.0,
                            height: 60.0,
                            decoration: BoxDecoration(
                                shape: BoxShape.circle,
                                image: DecorationImage(
                                    image: imageProvider,
                                    fit: BoxFit.contain))),
                        fit: BoxFit.contain,
                        imageUrl:
                            "${Constants.MEDIA_LINK}${state.review.company.logo}"),
Heeley answered 9/10, 2020 at 17:4 Comment(0)
Y
1
Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  GestureDetector(
                    onTap: () {
                      Navigator.push(
                        context,
                        MaterialPageRoute(builder: (context) => MyApp7()),
                      );
                    },
                    child: CircleAvatar(
                      radius: 50,
                      // backgroundColor: Colors.amber,
                      child: CircleAvatar(
                          backgroundColor: Colors.grey[50],
                          radius: 50,
                          // child: Image.asset("assets/images/nophotoMale.png")
                          backgroundImage:
                              AssetImage("assets/images/nophotoMale.png")),
                    ),
                  ),
                ],
              ),
Youngs answered 18/11, 2020 at 8:33 Comment(2)
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.Messidor
Yeah Sure I will AddYoungs
K
1

Below worked in my case:

child: new CircleAvatar(
        backgroundColor: Colors.white,
        child: ClipRect(
          child: Image.network(
            'url-to-image',
            fit: BoxFit.cover,
          ),
        ),
      )
Keats answered 23/5, 2021 at 12:33 Comment(0)
R
0

It took a few tries to figure this one out.. All these answers did not help me. In the end picture that I inserted into the circle avatar was stretched out to the boundaries of the container that was 2 instances above it. Maybe there are are people who, after going through the answers here, still have the problem that I had. I solved the constraint issue with a FittedBox

             GestureDetector(
                    onTap: () => getImage(),
                    child: Container(
                      width: MediaQuery.of(context).size.width,
                      decoration: BoxDecoration(
                        color: Colors.orange,
                      ),
                      //padding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
                      child: Container(
                          width: 140,
                          height: 160,
                          child: FittedBox(
                            child: picture(),
                          )),
                    ),
                  ),

This is the code for the picture() that I use. I think that the container inside the picture() is not necessary anymore, try it yourself :)

Widget picture() {
if (_image == null) {
  return CircleAvatar(
      radius: 70,
      child: Icon(
        Icons.person,
        size: 150,
        color: Colors.grey[900],
      ));
} else {
  return Container(
    width: 140,
    height: 140,
    child: CircleAvatar(
      radius: 70,
      backgroundImage: FileImage(_image),
    ),
  );
}
Reincarnate answered 11/8, 2020 at 7:10 Comment(0)
O
0

in this solution you can resize the image by container and clip image by clip Oval then add shadow to the image by card.

Container(
  width: 100,
  height: 100,
  child: InkWell(
    onTap: () {},
    child: Card(
      elevation: 5,
      shape: RoundedRectangleBorder(
        side: BorderSide(color: Colors.grey),
        borderRadius: const BorderRadius.all(
          Radius.circular(45.0),
        ),
      ),
      child: Container(
        child: ClipOval(
            child: CachedNetworkImage(
          imageUrl: '{image-url}',
          imageBuilder: (context, imageProvider) => Container(
            decoration: BoxDecoration(
              image: DecorationImage(
                image: imageProvider,
                fit: BoxFit.fill,
              ),
            ),
          ),
          placeholder: (context, url) => Container(
            height: 5,
            width: 5,
            child: CircularProgressIndicator(
              valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
            ),
          ),
          errorWidget: (context, url, error) => Icon(Icons.error),
        )),
      ),
    ),
  ));
Okra answered 24/10, 2020 at 0:56 Comment(0)
P
0

This is work for me. I think that best way

           CircleAvatar(
                          radius: 30,
                          backgroundColor: Colors.blueGrey.shade100,
                          child: Container(
                            clipBehavior: Clip.antiAlias,
                            decoration: const BoxDecoration(shape: 
                            BoxShape.circle),
                            child: const CachedNetworkImage(
                              url: "https://www.yourimage.com",
                            ),
                          ),
                        )
Plate answered 28/12, 2022 at 12:47 Comment(0)
P
0

A great way to do it is like this:

class CircleImage extends StatelessWidget {
  final Widget backgroundImage;
  final double radius;
  final Color colorBask;
  const CircleImage({super.key, required this.backgroundImage, required this.radius, required this.colorBask});
  @override
  Widget build(BuildContext context) {
    return  Container(
      width: radius,
      height: radius,
      decoration: BoxDecoration(
        color: colorBask,
        shape: BoxShape.circle,
      ),
      child: ClipOval(
        child: Container(
          padding: EdgeInsets.all(radius/5),
          width: radius/2,
          height: radius/2,
          child:  backgroundImage,
        ),
      ),
    );
  }
}

call like this:

            CircleImage(
              radius: 60.0,
              colorBask: colorScheme.surface,
              backgroundImage: Image.asset(
                'assets/img.png',
                fit: BoxFit.contain,
              ),
            ),
Podvin answered 25/1 at 1:54 Comment(0)
M
-1

Came here as I also had the issue with CirclAvatar and AppBar, where the image would stretch in height. Instead of a radius, as I'm not able to provide it with the component I'm using, I just wrapped the image with a colum when used in appbar. This makes the image not stretch in height. This way I can always control size from the outside too

Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  SizedBox(height: 40, width: 40, child: ProfileBadge(),),
                ],
              )
Monagan answered 6/1, 2020 at 11:58 Comment(0)
R
-1

Use AvatarView lib https://pub.dev/packages/avatar_view which provides the functionality to show network/asset images in circular/rectangular form.

To use add below dependency

dependencies:
  avatar_view: ^1.0.0+3

Example:

        AvatarView(
                  radius: 60,
                  borderColor: Colors.yellow,
                  avatarType: AvatarType.CIRCLE,
                  backgroundColor: Colors.red,
                  imagePath:
                  "https://images.pexels.com/photos/415829/pexels-photo-415829.jpeg?cs=srgb&dl=pexels-pixabay-415829.jpg",
                  placeHolder: Container(
                    child: Icon(Icons.person, size: 50,),
                  ),
                  errorWidget: Container(
                    child: Icon(Icons.error, size: 50,),
                  ),
                ),

It also provide funtionality to add borders around widget, for more example visit above link

Output:

enter image description here

Redraft answered 15/1, 2021 at 18:0 Comment(0)
P
-2

this worked for me

Transform.scale(
        scale: 0.6,
        child: ClipOval(
          child: Image.network(
            <IMAGE URL HERE>,
          ),
        ),
      )
Paige answered 17/12, 2020 at 9:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.