[Disponível em Português aqui]
Hi there.
In this Flutter tip I want to talk a bit about the UnconstrainedBox
widget, have you ever used it before? Let me know in the comments.
What is it for?
In short, it is a widget that gives its child the freedom to size itself as needed. UnconstrainedBox
(as the name suggests), impose no constraints on its child, the child will render as if it were in a infinite canvas. Sometimes it may overflow when used with some widgets like PageView
, so you must be careful to give its child a proper size constraints as required.
Learn by Example
Let's say we need to build a PageView
where their children have different sizes and it should show one item at time, how would you do that? (let me know in the comments)
Here is our initial code, it is just a PageView
with three items: a red, green and blue container.
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: UnconstrainedBoxSample()));
class UnconstrainedBoxSample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(title: Text('Unconstrained Box')),
body: PageView(
children: [
Container(color: Colors.red),
Container(color: Colors.green),
Container(color: Colors.blue),
],
),
);
}
}
Here is the output of the code above.
As you can see all three items are being expanded to fit the entire page, setting a custom size for our children doesn't work because PageView
forces them to have the same size (in the non-scrolling direction) as itself.
We can work around this by changing the page's viewport but it would have a side effect: other items would be displayed as well and our children would still being forced to have the same height as the PageView
.
Let's try that, add a controller with a custom view port fraction into your page view:
controller: PageController(viewportFraction: .8)
and the result is as follow.
This happens because PageView
is imposing constraints for its children. The default (viewportFraction: 1
) means that each child must have the exact same size as its parent (the PageView
). Each time you decrease the viewportFraction
you are just decreasing the size of its children.
UnconstrainedBox in action!
To solve the issues mentioned above, we should wrap each child into a unconstrained box.
Notice that even though we are using an unconstrained box, our item still have the constraints of: not being able to be bigger (in height/width depending on the scroll direction) than the PageView. The main advantage is to be able to have smaller (in size) children than the PageView
.
Remember: since we are using a unconstrained box, our child must have size otherwise it will have its width and height set to zero (0
).
Let's update our code, wrap your second item into a UnconstrainedBox
and give the container a size, our code now looks like this:
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: UnconstrainedBoxSample()));
class UnconstrainedBoxSample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(title: Text('Unconstrained Box')),
body: PageView(
children: [
Container(color: Colors.red),
UnconstrainedBox( // NEW
child: Container(
height: 400, // NEW
width: 250, // NEW
color: Colors.green,
),
), // NEW
Container(color: Colors.blue),
],
),
);
}
}
Here is the output:
Finally our second child now have the freedom to size itself as needed, as long as it does not oversize the PageView's size. This widget comes with some useful properties like alignment
and constrainedAxis
.
alignment
: allows you to align the child in its remaining space. Defaults toAlignment.center
.constrainedAxis
: you can specify an axis to constrain the child, in other words this allows to define in which direction your widget should still be constrained. Defaults tonull
which means neither axis will be constrained.
This widget gives us freedom and the hability to build great animations and UI using in conjuction with PageView
and other widgets.
That is it for today. Like share and subscribe for more Flutter tips. Comment if you have any question or issue.
Top comments (1)
So So much thank you I've been terribly looking for how to show overflow image in pageview when Boxfit is cover. so much thank you I did subscribe right away.