Flutter 网络图像不适合圆形头像

Posted

技术标签:

【中文标题】Flutter 网络图像不适合圆形头像【英文标题】:Flutter Network Image does not fit in Circular Avatar 【发布时间】:2019-04-30 00:10:33 【问题描述】:

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

这是我正在使用的代码

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

我尝试使用BoxFit 的所有属性,例如covercontainfitWidthfitHeight 等,但它们都不起作用。

【问题讨论】:

你试过fit: BoxFit.cover吗? 只需将 backgroundImage 属性与 CircleAvatar 一起使用。 6 Flutter CircleAvatar Examples With Tutorial 【参考方案1】:

以下在我的情况下有效:

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

【讨论】:

【参考方案2】:

你可以这样做

创建一个用户Avtar类

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

【讨论】:

【参考方案3】:

使用 AvatarView 库 https://pub.dev/packages/avatar_view,它提供了以圆形/矩形形式显示网络/资产图像的功能。

要使用添加下面的依赖项

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

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

输出:

【讨论】:

【参考方案4】:

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

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

【讨论】:

这应该被接受的答案【参考方案5】:

这对我有用

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

【讨论】:

【参考方案6】:
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")),
                    ),
                  ),
                ],
              ),

【讨论】:

虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。 是的,我会添加【参考方案7】:

只需在CircleAvatar 内使用 backgroundImage

 CircleAvatar(
      backgroundImage: AssetImage("assets/images/dia.jpg",),
    ),

【讨论】:

【参考方案8】:

如果有人试图在应用栏操作中放置圆形图像。尝试以下解决方案,它应该可以工作。

         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来控制圆形图片的大小。

【讨论】:

【参考方案9】:

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

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

【讨论】:

【参考方案10】:
                    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"),

【讨论】:

【参考方案11】:

尝试了几次才弄清楚这一点。所有这些答案都没有帮助我。最后,我插入到圆形头像中的图片被拉伸到容器的边界,该容器在其上方 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()里面的容器已经不用了,自己试试吧:)

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

【讨论】:

【参考方案12】:
 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,
                ),
        ),
      ),

【讨论】:

【参考方案13】:

您需要使用NetworkImageAssetImageFileImageMemoryImage 或类似名称。由于 Flutter 构建图像类的方式,您不能直接使用 Image.networkImage.asset 或类似名称。

一个例子:

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

CircleAvatar 中的backgroundImage 期望接收ImageProvider 作为参数。但是,Image.network 等并没有直接扩展ImageProvider 类,它们只是扩展了StatefulWidget 类,尽管它们在内部使用了NetworkImage。这就是为什么您在其他答案中看到正在使用 ClipOvalClipRRect 的原因。这些类接受Widget,因此它们不像CircleAvatar 和类似的类那样特别。

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

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

【讨论】:

【参考方案14】:

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

CircleAvatar(

             radius:25.0,

             backgroundImage: NetworkImage(
                        '$image_url',


                        ),
                        backgroundColor: Colors.blue,
                            ),   

【讨论】:

【参考方案15】:

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

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

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

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

【讨论】:

其实是最完美的实现。适用于所有图像尺寸,并且不会以任何方式扭曲图像。谢谢【参考方案16】:

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

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

【讨论】:

【参考方案17】:

这对我有用

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

【讨论】:

【参考方案18】:

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

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

【讨论】:

【参考方案19】:

我遇到了同样的问题

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

解决了我的问题。

【讨论】:

【参考方案20】:

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

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

【讨论】:

【参考方案21】:
  ClipOval(
     child: Image.asset(
      'assets/dummy.jpg',
       fit: BoxFit.contain,
       matchTextDirection: true,
       height: 50,
   ))

【讨论】:

虽然此代码可能/可能无法解决问题,including an explanation 关于如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请编辑您的答案以添加解释。【参考方案22】:

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

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

【讨论】:

【参考方案23】:

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

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

【讨论】:

为什么有人不尝试圈子头像 @AsbahRiyas 因为图像没有填满可用空间。尝试在非常小的圆形头像中使用大图像,然后您就会知道问题所在。 我不使用 CircleAvatar 的一个原因是它会为背景颜色设置动画,这是我不想要的。换句话说,这个解决方案对我来说是完美的,谢谢。【参考方案24】:

AppBar 操作小部件列表中存在类似问题。

这对我有用:

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

【讨论】:

【参考方案25】:

这将起作用:您需要使用 backgroundImage:property 才能将其放入 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,
              )

【讨论】:

还有来自存储的图像,Image.file(Image.file(File file))。 CircleAvatar 能应付吗? @M.ArslanKhan 是的。您可以在 backgroundImage 属性中使用 AssetImage。 有时您会想像我一样将它与 FadeInImage 一起使用...在这种情况下,最好的方法是将其包装在 ClipOval 小部件中...这是一个 sn-p:@987654324 @

以上是关于Flutter 网络图像不适合圆形头像的主要内容,如果未能解决你的问题,请参考以下文章

Flutter实现圆形头像的几种方法

Flutter——CircleAvatar组件(圆形头像组件)

如何检查图像资产是不是存在,然后将其用作圆形头像或在圆形头像中写下姓名的第一个字母

对齐两个圆形头像的最佳方法是啥?

Flutter CircleAvatar backgroundImage没有填满圆圈

登录圆形头像之网络加载与缓存到本地