Reputation: 451
When I place an Image.network in either a Row or Container which is the child of a FittedBox, viewing it causes errors/crashes.
The FittedBox actually uses a function as its child which returns a widget based on number of images. When there are two images it returns a Row which has each image as its children, which works without error, but when there is only one the error occurs whether I return either a Container with the image as its child or a Row with a Single child being the image.
Container(
child: FittedBox(child: status.statusFiles()),
),
statusFiles:
return Container(
child:
Image.network(
this.files[0].thumbnailUrl,
fit: BoxFit.contain,
),
);
I expect a FittedBox containing the image in the largest size that fits the, instead I get the following error when the widget is rendered
I/flutter (26617): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (26617): The following assertion was thrown during performLayout():
I/flutter (26617): 'package:flutter/src/rendering/box.dart': Failed assertion: line 307 pos 12: 'width > 0.0': is not
I/flutter (26617): true.
...
I/flutter (26617): When the exception was thrown, this was the stack:
I/flutter (26617): #2 BoxConstraints.constrainSizeAndAttemptToPreserveAspectRatio (package:flutter/src/rendering/box.dart:307:12)
I/flutter (26617): #3 RenderFittedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:2275:26)
I/flutter (26617): #4 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
I/flutter (26617): #5 RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:738:15)
I/flutter (26617): #6 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
I/flutter (26617): #7 RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:798:17)
I/flutter (26617): #8 RenderObject.layout (package:flutter/src/rendering/object.dart:1634:7)
I/flutter (26617): #9 RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:199:11)
...
I/flutter (26617): The following RenderObject was being processed when the exception was fired:
I/flutter (26617): RenderFittedBox#d752c relayoutBoundary=up8 NEEDS-LAYOUT NEEDS-PAINT
I/flutter (26617): creator: FittedBox ← Container ← Column ← Expanded ← Row ← Padding ← Container ←
I/flutter (26617): RepaintBoundary-[<16>] ← IndexedSemantics ← NotificationListener<KeepAliveNotification> ←
I/flutter (26617): KeepAlive ← AutomaticKeepAlive ← ⋯
I/flutter (26617): parentData: offset=Offset(0.0, 0.0); flex=null; fit=null (can use size)
I/flutter (26617): constraints: BoxConstraints(0.0<=w<=339.4, 0.0<=h<=Infinity)
I/flutter (26617): size: MISSING
I/flutter (26617): fit: contain
I/flutter (26617): alignment: center
I/flutter (26617): textDirection: ltr
I/flutter (26617): This RenderObject had the following descendants (showing up to depth 5):
I/flutter (26617): RenderSemanticsAnnotations#df6f3 relayoutBoundary=up9 NEEDS-PAINT
I/flutter (26617): RenderImage#63da1 relayoutBoundary=up10 NEEDS-PAINT
I/flutter (26617): ════════════════════════════════════════════════════════════════════════════════════════════════════
Upvotes: 22
Views: 16229
Reputation: 1
I had similar problem with widget Visibility. Solution:
Visibility(
maintainSize: true,
maintainAnimation: true,
maintainState: true,
// the free flags true so when visible = false, keeps the widget on the tree
visible :provider1.visivility[index],
)
Upvotes: 0
Reputation: 50
minWidth hide this error - work good in some cases:
Container(
child: FittedBox(
fit:BoxFit.scaleDown,
Container(
constraints:const BoxConstraints(minWidth:1), // Set Min Width
child: status.statusFiles(),
),
),
),
Upvotes: 1
Reputation: 1
i had the same problem when i used video player in FittedBox, i used : ConstrainedBox( constraints: BoxConstraints(minWidth: 1, minHeight: 1), child: Image.asset( 'resources/images/background.png', ), ),
or : SizedBox.expand( child: FittedBox( child: Image.file(File(path)), fit: BoxFit.fill, ), ),
Upvotes: 0
Reputation: 5501
This is my workaround, but I think the Konstantin Kozirev's answer is better
final image = Image.asset("assets/something.png");
...
FutureBuilder(
future: Future.delayed(Duration(milliseconds: 100)).then((_) => image),
builder: (context, snapshot) {
if(snapshot.hasData) {
return FittedBox(
fit: BoxFit.scaleDown,
child: image,
);
}
return image;
},
)
Upvotes: 0
Reputation: 1262
It is strongly recommended that either both the width and the height be specified for an Image
widget, or that the widget be placed in a context that sets tight layout constraints, so that the image does not change size as it loads.
So if you don't want to specify height/width, you have an option to put the FittedBox
into ConstrainedBox
that has minWidth
of infinity
.
Thus we don't need minWidth/minHeight: 1
here.
Upvotes: 1
Reputation: 5943
Sizebox.expand solved my problem
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(3),
color: color,
),
child: SizedBox.expand(
child: FittedBox(
child: Image.file(File(path)),
fit: BoxFit.fill,
),
),
)
Upvotes: 18
Reputation: 958
Neither of the previous solutions worked for me because I used fit: Boxfit.fitWidth
and I really needed the height of the ancestors to depend on the image width.
My solution was to wrap the image in a ConstrainedBox and manually apply a min. height and width of 1:
ConstrainedBox(
constraints: BoxConstraints(maxHeight: maxHeight),
child: Hero(
tag: 'SettingsPic',
child: Container(
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.vertical(bottom: Radius.circular(25)),
boxShadow: [BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 10
)]
),
child: ClipRRect(
borderRadius: BorderRadius.vertical(bottom: Radius.circular(25)),
child: FittedBox(
fit: BoxFit.fitWidth,
alignment: Alignment.bottomCenter,
child: ConstrainedBox(
constraints: BoxConstraints(minWidth: 1, minHeight: 1), // here
child: Image.asset(
'resources/images/background.png',
),
),
),
),
),
),
)
Upvotes: 25
Reputation: 24157
The reason why this is not working is because it does not know the width of the image because the image has yet to be loaded at the point of laying out the component. It needs the width of the image to do the calculation. When you do a hot reload the image will have been retrieved by Flutter at that point.
What I did in this situation is go through all my images and find out the dimensions and I hardcoded them into the file. I don't like this solution but it did solve my error.
I assume that the assets are retrieved from the assets directory only when they are required for performance reasons (ie, it would cause a lag at phone startup time if you had many images)
Expanded(
child: Column(
children: [
FittedBox(
fit: BoxFit.scaleDown,
child: Image.asset("assets/foot.png", width: 100, height: 100,),
),
],
),
),
Upvotes: 10