Flutter SizedBox vs LimitedBox - flutter

I have read docs for both SizedBox and LimitedBox, and didn't find any practical difference between the two.
Can anyone give an example when one may fail and other work?

So what I have found is, LimitedBox is only usable when the child is given unconstrained width/height by its parent.
And SizedBox simply creates a box with given width/height and doesn't allow child to go beyond given dimensions.
Example: (LimitedBox)
#override
Widget build(BuildContext context) {
return Scaffold(
body: LimitedBox(
maxHeight: 50, // no impact because it's child `Text` width/height isn't unconstrained
child: Text(
"A",
style: TextStyle(fontSize: 200),
),
),
);
}
Example (SizedBox)
#override
Widget build(BuildContext context) {
return Scaffold(
body: SizedBox(
height: 50, // has impact, it won't let Text to be of more than 50 logical pixels high
child: Text(
"A",
style: TextStyle(fontSize: 200),
),
),
);
}
Note: If anyone has better answer, I am happy to accept theirs.

LimitedBox is a SizedBox unless the parent widget imposes a constraint.
From Doc
A box that limits its size only when it's unconstrained.
Reference
Flutter doc

LimitBox:
LimitBox works only when it's size is unconstrained If this widget's
maximum width is unconstrained then its child's width is limited to
[maxWidth]. Similarly, if this widget's maximum height is
unconstrained then its child's height is limited to [maxHeight].
Example:
Center(
child: LimitedBox(
maxWidth: 50,
child: Container(
color: Colors.red,
width: 20,
height: 100,
)
),
),
Output:
This restricts Container Widget with a max-width as 50 but it's going to show widget till container width which is 20.
SizeBox:
It comes with fixed sizes that restrict its child to render on the
limited area. If either the width or height is null, this widget will
try to size itself to match the child's size in that dimension. If the
child's size depends on the size of its parent, the height and width
must be provided.
Example:
Center(
child: SizedBox(
width: 50,
child: Container(
color: Colors.red,
width: 20,
height: 100,
)
),
),
Output:
This will also behave like LimitedBox but the only difference here Container will be rendered till width 50 of SizeBox, it will not consider it's own width which is 20 and drawn till the parent widget.

Can anyone give an example when one may fail and other work?
They'll both work, but they'll do different things. The example from the LimitedBox documentation says:
This is useful when composing widgets that normally try to match their parents' size, so that they behave reasonably in lists.
Imagine that you are creating a reusable widget and don't have control over where it's used. You could use a SizedBox, but then your widget will always have the specified size, even if its size is already constrained by a parent widget.

Related

Flutter Container inside a Container and Text widget

Container(
color: Colors.green,
width: 300,
height: 300,
child: Container(
color: Colors.purple,
width: 200,
height: 200,
),
),
when I do this why the child container size is the same as parent container size? but when i pass alignment: Alignment.center inside the parent container, this give a expected output?
Output
Because the parent widget forces the child widget to be the same exact size.
From the docs:
If a child wants a different size from its parent and the parent
doesn’t have enough information to align it, then the child’s size
might be ignored. Be specific when defining alignment.
You could also wrap the inner Container in a Center widget and it would also work.
See the examples here https://docs.flutter.dev/development/ui/layout/constraints

Why does a SizedBox in another SizedBox ignore its width and hight?

When I nest two SizedBoxes, the width and height of the inner box are ignored. Why is this, how can I work around it?
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: SizedBox(
width: 300,
height: 500,
child: SizedBox(
width: 200, height: 200, child: Container(color: Colors.green)),
));
}
}
In this example, I have a 300x500 sized box and an inner 200x200 SizedBox. In the picture you can see that the green box is the size of the outer SizedBox but should actually be a 200x200 square.
According to flutter documentation: If given a child, this widget forces it to have a specific width and/or height. These values will be ignored if this widget's parent does not permit them. For example, this happens if the parent is the screen (forces the child to be the same size as the parent), or another SizedBox (forces its child to have a specific width and/or height). This can be remedied by wrapping the child SizedBox in a widget that does permit it to be any size up to the size of the parent, such as Center or Align.
So wrapping the child with center would solve the problem:
Center(
child: SizedBox(
width: 300,
height: 500,
child: Center(
child: SizedBox(
width: 200, height: 200, child: Container(color: Colors.green)),
),
)),
The problem is, SizedBox can set widget size only within the constrains set by the parent. Many widgets, like Padding, want their child to occupy 100% of the space available to them. This makes sense, because if the child is smaller they wouldn't know where to put it.
If you want the child to be smaller than the parent you could use Center or Align, e.g. replace
I had the same issue and I solved my problem using the FractionallySizedBox class.
You can specify the suitable size using fractions of the above SizedBox as widthFactor and heightFactor:
Widget build(BuildContext context) {
return SizedBox.expand(
child: FractionallySizedBox(
widthFactor: 0.5,
heightFactor: 0.5,
alignment: FractionalOffset.center,
child: DecoratedBox(
decoration: BoxDecoration(
border: Border.all(
color: Colors.blue,
width: 4),
),
),
),
);
}

Incoming constraints for Container in Flutter. Do i get it wrong?

As documentation says
Containers with no children try to be as big as possible unless the
incoming constraints are unbounded, in which case they try to be as
small as possible
Well when I make incoming constraints unbounded for inner Container i suppose that it should be as small as possible but it expands for entire screen.
body: Container(
color: Colors.red,
constraints: const BoxConstraints(
maxHeight: double.infinity,
maxWidth: double.infinity,
),
child: Container(
color: Colors.green,
),
),
Why?
If you read the documentation a bit further, you'll see that constraint arguments on the Container itself will override this behavior:
Containers with no children try to be as big as possible unless the incoming constraints are unbounded, in which case they try to be as small as possible. Containers with children size themselves to their children. The width, height, and constraints arguments to the constructor override this.
Try wrapping the inner childless Container in an UnconstrainedBox, and you'll see it will shrink to zero width and height.
body:
Container(
color: Colors.red,
width: double.infinity,
height:double.infinity,
child: UnconstrainedBox(
child: Container(
color: Colors.green,
),
),
)
Although red container has infinite size, You put it in a scaffold's body which has specific size. so your red container get specific size then your grin container with no child get size as much as its parents.
The red container actually will has size as small as posibble depends its child.
the green container has no child, then as the documentation said it will try to be as big as possible unless the incoming constraints are unbounded,
if you change the child , like Text widget, or Column, or other widget, it will not get the maximum size.

Keep Flutter widget at fixed size upon resizing window

I have the following in my widget's build method:
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Title bar'),
),
body: Center(
child: SizedBox(
width: 250,
child: ListView(
children: [
const Text('Text goes here'),
Container(
width: 250,
height: 250,
color: Colors.green,
child: Texture(textureId: textureId)), // ID of a texture that displays pixels
],
),
),
),
floatingActionButton: FloatingActionButton(
child: const Text('Button'),
onPressed: () {
noisy();
},
),
));
What I want to have take place is that the Texture widget is always 250x250 pixels, regardless of what I resize the window to. When I resize the window vertically, this is what happens, and the overflow of the widget that goes past the bottom of the screen is just clipped and ignored. However, when I resize horizontally making the window less wide than the widget, the widget is scaled horizontally, getting compressed in that direction instead of being clipped to the right. What arrangement if widgets would I need in order to keep the Container/Texture at 250x250 pixels and have it clipped past the end of the window instead of being compressed?
I have tried surrounding the inner Container in another horizontal ListView, as the outer ListView appears to clip the window vertically correctly, but that causes RenderBox was not laid out: RenderRepaintBoundary#51231 relayoutBoundary=up5 NEEDS-PAINT.... I also attempted placing that inner ListView in another Container/SizedBox, though this did not fix the shrinking issue and cause it to clip instead.
Try using unconstrainedBox
UnconstrainedBox(
child: SizedBox(
)
)
This allows a child to render at the size it would render if it were alone on an infinite canvas with no constraints. This container will then attempt to adopt the same size, within the limits of its own constraints. If it ends up with a different size, it will align the child based on alignment. If the box cannot expand enough to accommodate the entire child, the child will be clipped.
In debug mode, if the child overflows the container, a warning will be printed on the console, and black and yellow striped areas will appear where the overflow occurs.
simple, use ConstraintBox & set it minHeight and minWidth
ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 100,
minHeight: 100,
maxWidth: 100,
maxHeight: 100,
),
)

BoxConstraints forces an infinite height

child:Column(
children: <Widget>[
Container(
height: double.infinity,
width: 100.0,
color: Colors.red,
child: Text('hello'),
),)
in this,when i make height:double.infinity,it gives error in run saying **BoxConstraints forces an infinite height.**but when i give height manually it work fine.
can anyone explain me why this happening.
How about this one.
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
children: <Widget>[
Expanded(
child: Container(
// height: double.infinity,
width: 100.0,
color: Colors.red,
child: Text('hello'),
),
),
],
),
),
);
}
}
This means that you can't offer inifite height to the container. It's obvious behaviour if you don't provide the contraints to height.
You have to specify limited height to the container so that flutter can render it, if you offer it infinite it how can flutter render that and up to which constraints it would do that !
Rather you can set double.infinity to width and flutter will successfully render that because by default flutter has constraints for width it will set width to width of screen.
Considering that you have to provide height as that of screen you can use MediaQuery for that
Widget yourMethod(or build)(BuildContext context){
final screenHeight = MediaQuery.of(context).size.height;
return Column(
children:<Widget>[
Container(
height:screenHeight,//but this will be height of whole screen. You need to substract screen default paddings and height of appbar if you have one
width:100.0,
....
)
]);
}
Hope this helps !
Happy coding..
BoxConstraints forces an infinite height
Why This Happens
You're asking to render an infinite height object without a height constraint... Flutter can't do that.
Column lays out children in two phases:
Phase 1: non-Flex items (anything not Expanded, Flexible or Spacer)
done in unconstrained space
Phase 2: Flex items (Expanded,Flexible, Spacer only)
done with remaining space
Phase 1
Column's phase 1 vertical layout is done in unbounded space. That means:
no vertical constraint → no height limit
any widget with infinite height will throw the above error
you can't render an infinite height object in an infinite height constraint... that's goes on forever
Phase 2
after Phase 1 widgets have taken as much space as they intrinsically need, phase 2 Flex items share the remaining/leftover space
the remaining space is calculated from incoming constraints minus Phase 1 widgets dimensions
double.infinity height will expand to use up the remaining space
Infinite Height is OK
Here's an example of using infinite height on a Container inside a Column, which is fine:
class ColumnInfiniteChildPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
Flexible(
child: Container(
height: double.infinity, // ← perfectly fine
child: Text('Column > Container > Text')),
),
Text('Column > Text')
],
),
),
);
}
}
Remove the Flexible and the error will be thrown.