Flutter Network Image 不适合圆形头像

Flutter Network Image does not fit in Circular Avatar

我正在尝试从 api 中检索一堆图像。我希望图像以圆形形式显示,所以我使用 CircleAvatar 小部件,但我一直在获取方形格式的图像。 这是图像的屏幕截图

这是我使用的代码

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

我尝试使用 BoxFit 的所有属性,例如 covercontainfitWidthfitHeight 等,但 none有效。

这会起作用:您需要使用 backgroundImage:属性 才能使其适合 Circle。

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

检查虚拟占位符:

CircleAvatar(
                radius: 30.0,
                backgroundImage:
                    NetworkImage('https://via.placeholder.com/150'),
                backgroundColor: Colors.transparent,
              )

AppBar 操作小部件列表中有类似的问题。

这对我有用:

CircleAvatar(
    radius: 18,
    child: ClipOval(
        child: Image.network(
          'image-url',
        ),
    ),
),

如果您不想使用 CircleAvatar,请按以下方法操作。

ClipOval(
  child: Image.network(
    'https://via.placeholder.com/150',
    width: 100,
    height: 100,
    fit: BoxFit.cover,
  ),
),

这是一张带阴影的圆形图片:

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)
            )
        )
    )
)
  ClipOval(
     child: Image.asset(
      'assets/dummy.jpg',
       fit: BoxFit.contain,
       matchTextDirection: true,
       height: 50,
   ))

使用 width/heightfit 的组合并将图像包装在 ClipOval 中,如下所示:

CircleAvatar(
    child: ClipOval(
        child: Image.network(
            _photo,
            width: 120,
            fit: BoxFit.fill
        ),
    ),
    radius: 50,
),

我遇到了同样的问题

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

解决了我的问题。

来到这里是因为我也遇到了 CirclAvatar 和 AppBar 的问题,图像会拉伸高度。因为我无法为我使用的组件提供半径,所以我只是在 appbar 中使用时用 colum 包裹了图像。这使得图像不会在高度上拉伸。这样我也可以随时从外面控制尺寸

Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  SizedBox(height: 40, width: 40, child: ProfileBadge(),),
                ],
              )

这对我有用

   CircleAvatar(
                  child:  ClipRRect(
                      borderRadius: new BorderRadius.circular(100.0),
                      child:Image.network("https://www.rd.com/wp-content/uploads/2017/09/01-shutterstock_476340928-Irina-Bg-1024x683.jpg"),
                ),),

如果你想显示你的图像覆盖整个圆形头像的宽度,那么你可以这样使用它。如果您的图像没有加载,那么它将显示默认的人物图标。

 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,
                        ),

您将需要使用 NetworkImageAssetImageFileImageMemoryImage 或类似的东西。由于 Flutter 如何构建其图像 classes.

,您不能直接使用 Image.networkImage.asset 或类似的

一个例子:

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

backgroundImage in CircleAvatar 期望接收 ImageProvider 作为参数。但是,Image.network 和其他人不直接扩展 ImageProvider class,他们只是扩展 StatefulWidget class,即使他们使用 NetworkImage里面。这就是为什么您在其他答案中看到 ClipOvalClipRRect 被使用的原因。这些 classes 接受 Widget,因此它们不像 CircleAvatar 和类似的 classes 那样特别。

因此,对于 CircleAvatar,您应该使用 NetworkImage 和类似的 classes 而不是这些解决方法,对于只需要 Widget 的小部件,您可以使用 Image.network 和类似的。

不使用剪辑的另一个原因是它们比直接更改边框半径更昂贵:https://flutter.dev/docs/perf/rendering/best-practices

如果有人打算创建带边框的圆形图像,试试这个。

使用 ClipOval 小部件不是完美的解决方案,因为如果图像不是方形的,结果将是椭圆形的。

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

ClipRRect 小部件防止图像溢出 CircleAvatar 小部件。

我遇到了同样的问题。在圆形头像中使用 clipoval 会使它变成椭圆形。 但这解决了这个问题。

CircleAvatar(

             radius:25.0,

             backgroundImage: NetworkImage(
                        '${image_url}',


                        ),
                        backgroundColor: Colors.blue,
                            ),   

 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,
                ),
        ),
      ),

我试了几次才弄明白。所有这些答案都没有帮助我。最后,我插入圆形头像的图片被拉伸到比它高 2 个实例的容器边界。也许有些人在看完这里的答案后,仍然遇到我遇到的问题。我用 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(),
                          )),
                    ),
                  ),

这是我使用的 picture() 的代码。我觉得picture()里面的容器已经没有必要了,自己试试吧:)

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),
    ),
  );
}
                    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}"),

在此解决方案中,您可以通过容器调整图像大小,通过剪辑椭圆剪辑图像,然后通过卡片向图像添加阴影。

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),
        )),
      ),
    ),
  ));

如果有人试图在应用栏操作中调整圆形图像。尝试下面的解决方案它应该有效。

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

              ),
            ),
          )

AspectRatio 首先尝试布局约束(这里是应用栏)允许的最大宽度。如果我删除填充图像半径将是 appbar 大小。所以添加padding来控制圆形图片的大小

只需在CircleAvatar

中使用backgroundImage
 CircleAvatar(
      backgroundImage: AssetImage("assets/images/dia.jpg",),
    ),
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")),
                    ),
                  ),
                ],
              ),

将您的 CircleAvatar 小部件包裹在 Stack 小部件下。

 return Stack(
      children: [
        CircleAvatar(
          radius: 50.0,
          backgroundImage: NetworkImage(
              'https://i.pinimg.com/474x/0c/eb/c3/0cebc3e2a01fe5abcff9f68e9d2a06e4.jpg'),
        ),
      ],
    );

这对我有用

Transform.scale(
        scale: 0.6,
        child: ClipOval(
          child: Image.network(
            <IMAGE URL HERE>,
          ),
        ),
      )

使用 AvatarView 库 https://pub.dev/packages/avatar_view,它提供以 circular/rectangular 形式显示 network/asset 图像的功能。

要使用添加下面的依赖

dependencies:
  avatar_view: ^1.0.0+3

示例:

        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,),
                  ),
                ),

它还提供了在小部件周围添加边框的功能,有关更多示例,请访问上面的 link

输出:

你可以这样操作

创建用户头像class

class Avatar extends StatelessWidget {
  Avatar(
    this.user,
  );
  final UserModel user;

  @override
  Widget build(BuildContext context) {
    if ((user?.photoUrl == '') || (user?.photoUrl == null)) {
      return LogoGraphicHeader();
    }
    return Hero(
      tag: 'User Avatar Image',
      child: CircleAvatar(
          foregroundColor: Colors.blue,
          backgroundColor: Colors.white,
          radius: 70.0,
          child: ClipOval(
            child: Image.network(
              user?.photoUrl,
              fit: BoxFit.cover,
              width: 120.0,
              height: 120.0,
            ),
          )),
    );
  }
}

然后像这样使用它

Avatar(controller.firestoreUser.value),

以下适用于我的情况:

child: new CircleAvatar(
        backgroundColor: Colors.white,
        child: ClipRect(
          child: Image.network(
            'url-to-image',
            fit: BoxFit.cover,
          ),
        ),
      )