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
的所有属性,例如 cover
、contain
、fitWidth
、fitHeight
等,但 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/height
、fit
的组合并将图像包装在 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,
),
您将需要使用 NetworkImage
、AssetImage
、FileImage
、MemoryImage
或类似的东西。由于 Flutter 如何构建其图像 classes.
,您不能直接使用 Image.network
、Image.asset
或类似的
一个例子:
CircleAvatar(
radius: 100.0,
backgroundImage: NetworkImage(...),
)
backgroundImage
in CircleAvatar
期望接收 ImageProvider
作为参数。但是,Image.network
和其他人不直接扩展 ImageProvider
class,他们只是扩展 StatefulWidget
class,即使他们使用 NetworkImage
里面。这就是为什么您在其他答案中看到 ClipOval
或 ClipRRect
被使用的原因。这些 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,
),
),
)
我正在尝试从 api 中检索一堆图像。我希望图像以圆形形式显示,所以我使用 CircleAvatar
小部件,但我一直在获取方形格式的图像。
这是图像的屏幕截图
这是我使用的代码
ListTile(leading: CircleAvatar(child: Image.network("${snapshot.data.hitsList[index].previewUrl}",fit: BoxFit.scaleDown,)),),
我尝试使用 BoxFit
的所有属性,例如 cover
、contain
、fitWidth
、fitHeight
等,但 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/height
、fit
的组合并将图像包装在 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,
),
您将需要使用 NetworkImage
、AssetImage
、FileImage
、MemoryImage
或类似的东西。由于 Flutter 如何构建其图像 classes.
Image.network
、Image.asset
或类似的
一个例子:
CircleAvatar(
radius: 100.0,
backgroundImage: NetworkImage(...),
)
backgroundImage
in CircleAvatar
期望接收 ImageProvider
作为参数。但是,Image.network
和其他人不直接扩展 ImageProvider
class,他们只是扩展 StatefulWidget
class,即使他们使用 NetworkImage
里面。这就是为什么您在其他答案中看到 ClipOval
或 ClipRRect
被使用的原因。这些 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,
),
),
)