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
的所有属性,例如cover
、contain
、fitWidth
、fitHeight
等,但它们都不起作用。
【问题讨论】:
你试过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】:您需要使用NetworkImage
、AssetImage
、FileImage
、MemoryImage
或类似名称。由于 Flutter 构建图像类的方式,您不能直接使用 Image.network
、Image.asset
或类似名称。
一个例子:
CircleAvatar(
radius: 100.0,
backgroundImage: NetworkImage(...),
)
CircleAvatar
中的backgroundImage
期望接收ImageProvider
作为参数。但是,Image.network
等并没有直接扩展ImageProvider
类,它们只是扩展了StatefulWidget
类,尽管它们在内部使用了NetworkImage
。这就是为什么您在其他答案中看到正在使用 ClipOval
或 ClipRRect
的原因。这些类接受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/height
、fit
的组合并将图像包装在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——CircleAvatar组件(圆形头像组件)
如何检查图像资产是不是存在,然后将其用作圆形头像或在圆形头像中写下姓名的第一个字母