Flutter: child button filling container size with explicit size - flutter

I'm trying to have a button nested in a container with a specific background color. I'm setting the height on the Container and on the MaterialButton nested within. I would expect the MaterialButton to maintain it's height of 40, while in the container of height 100. Instead, the MaterialButton is stretch to the height and width of the container.
Container(
color: lightBackground,
height: 100,
width: double.infinity,
child: MaterialButton(
height: 40,
child: Text('Hi'),
color: primaryColor,
onPressed: () {},
))
Anyone know how to get round this? Thanks.

The simple solution is to set alignment: Alignment.center for the Container, or wrap the Button with a Center widget.
For example:
Container(
height: 100,
alignment: Alignment.center,
child: ...
)
The long explanation has to do with Flutter Layout Constraints. You can read more about it at the official doc here.

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

Draw a stripe with Box decoration

I want to decorate a container with a single stripe down the middle with white on each side like in the picture, I'm guessing I need to use Linear Gradient but I am struggling to get it right.Any Ideas?
Single Stripe Pic
Easy, You need to create a container and make a child of it as Stack and further create a container with aligned it to center. Give it some width and decorate it with linear gradient that's all
Here's some code I've written to help you. Feel free to customize on top of it and use within your app. Cheers!
Container(
width: 200,
height: 150,
color: Colors.white,
child: Stack(
children: [
Align(
alignment: Alignment.center,
child: Container(
width: 50,
color: Colors.red,
),
)
],
),
);

Why parent Container constraints are respected by child Container when OverflowBox is provided?

Minimal code:
Widget build(_) {
return Scaffold(
body: Container(
width: 100, // 'A' width
height: 30,
child: OverflowBox(
maxWidth: 400, // 'B' width
child: Container(
width: 200, // 'C' width
color: Colors.white,
),
),
),
);
}
If you chang A width to 0, you'll find the the width (C) of white Container decreases which shouldn't happen because I'm providing OverflowBox which seems to provide its own constraints to its child to let it overflow.
In my understanding, the constraints passed by 1st Container shouldn't have any impact on 2nd Container as long as OverflowBox provides its own max/min to it.
Output:

Flutter Container not wrapping to size of container when alignment property is used

I have a container A and a container B such that container A contains container B.
I expect the the container A to wrap itself to the size of the child ie. container B as a container is defined in Flutter doc.
It works as expected and the container A size wraps just to fit the Container B. Very well
However, when alignment property is used on the container A, the Container A extends full height without honouring the height of the container B.
Here is my code :
Container(
alignment: Alignment.bottomLeft,
child : Container(child: SizedBox(width:30, height: 300,), color: Colors.green,),
width: 60,
color: Colors.blue,
)
How can I use alignment property of the container expecting normal behaviour?
According to chat conversation this is the required outcome
Container(
color: Colors.red,
child: Row(
children: <Widget>[
Container(
height: 300,
width: 30,
color: Colors.green,
)
],
),
)
I have a second question on this regard..if you can answer. What if i
reverse my case and would want to have my child align to right and
have a breather space to its left?
Add mainAxisAlignment: MainAxisAlignment.end inside your row

Make container widget fill parent vertically

TL;DR Need the container to fill the vertical space so that it can act as a ontap listener. Have tried most solutions but nothing seems to work.
So what I am trying to do is to make my container fill up the vertical space while still having a fixed width. Two first is what I have and third is what I want. The idea is to have the container transparent with a gesture ontap listener. If anyone have a better idea as for a different solution, feel free to suggest.
Widget build(BuildContext context) {
return new GestureDetector(
onHorizontalDragUpdate: _move,
onHorizontalDragEnd: _handleDragEnd,
child: new Stack(
children: <Widget>[
new Positioned.fill(
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new Container(
child: new IconButton(
padding: new EdgeInsets.only(top: 16.0, bottom: 16.0, left: 24.0, right: 24.0),
icon: new Icon(Icons.warning),
color: Colors.black12,
onPressed: () {},
)
),
],
),
),
new SlideTransition(
position: new Tween<Offset>(
begin: Offset(0.0, 0.0),
end: const Offset(-0.6, 0.0),
).animate(_animation),
child: new Card(
child: new Row(
children: <Widget>[
new Container(
width: 20.0,
height: 20.0,
color: Colors.amber,
),
new Expanded(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
_getListTile(),
_ifStoplineIsToBeShown()
],
),
)
],
)
),
),
],
)
);
}
I am quite sure that i have been missing something considering the fact that I have tried a lot of different things and nothing seems to work.
I have also uploaded an image with the debug painting here.
PS. I know I have set the height to a fixed value, but this is the only way to show the container.
The trick is to combine an IntrinsicHeight widget and a Row with crossAxisAlignment: CrossAxisAlignment.stretch
This force the children of Row to expand vertically, but Row will take the least amount of vertical space possible.
Card(
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
width: 20.0,
color: Colors.amber,
),
// Expanded(...)
],
),
)
)
To stretch the container to full height of the parent use property constraints:BoxConstraints.expand() in container widget. Container occupy the complete space independent of the of child widget
Container(
color: Colors.green,
child: Text("Flutter"),
constraints: BoxConstraints.expand(),
)
Please refer the link Container Cheat sheet for more about container
Simply pass in: double.infinity.
If you want a Container to fill all available space, you can just pass in:
width: double.infinity,
height: double.infinity
Explanation:
In Flutter, a child widget cannot exceed the "layout constraints" imposed by its parent widget. During the layout phase, Flutter engine uses a constraint solver to automatically correct "out-of-bound" values into what's allowed by its parent constraints.
For example, if you have a Container that's 50x50, and for its child, you pass in another Container that's 300x300, the inner container will be automatically corrected to "not exceed its parent", thus 50x50. Therefore, using sufficiently large values would always make sure you "fill parent".
In fact, even BoxConstraints.expand() exploits the same idea internally. If you open up the source code of expand(), you will see:
/// Creates box constraints that expand to fill another box constraints.
///
/// If width or height is given, the constraints will require exactly the
/// given value in the given dimension.
const BoxConstraints.expand({
double width,
double height,
}) : minWidth = width ?? double.infinity,
maxWidth = width ?? double.infinity,
minHeight = height ?? double.infinity,
maxHeight = height ?? double.infinity;
So if you are absolutely certain you want to fill all spaces, you can intuitively pass in a number bigger than the parent (or larger than the whole screen), like double.infinity.
As of Jan 2020 the simplest is to use an Expanded Widget
Expanded(flex: 1,
child: Container(..),
),
https://api.flutter.dev/flutter/widgets/Expanded-class.html
There are many answers which suggest using two things
constraints: BoxConstraints.expand(),
height: double.infinity,
But both these answer will give you an error like
BoxConstraints forces an infinite height.
We can avoid these by calculating the height of the screen like
App Bar
Top Bar Space(Exist on the above App Bar)
Remaining screen
1. Get the MediaQuery
final mediaQuery = MediaQuery.of(context);
2. Declare the AppBar Widget and same App Bar instance should be used in Scaffold App Bar
final PreferredSizeWidget appBar = AppBar(
title: Text('Home'),
);
3. Use calculated height
Container(
width: mediaQuery.size.width,
height: (mediaQuery.size.height -
appBar.preferredSize.height -
mediaQuery.padding.top),
color: Colors.red,
),
Output:
Set the height or width of a container to double.maxFinite
Container(
height: double.maxFinite,
width: 100,)
You can make your widget take the full size of a Container widget, and then set the container's height and/or width to double.maxFinite. This will make the Container take the height and/or width or its parent widget
I propose using Expanded widget (which allows us to avoid IntrinsicHeight widget), combine it with the Container's alignment property and therefore make it work properly even if the Container is not the only one at the screen.
Expanded(
child: Container(
alignment: Alignment.center,
child: Text('Your text', textAlign: TextAlign.center))),
That way one also avoids potential app's crash which occurs often when you accidentally expand to infinity some parts of the widget tree both horizontally and vertically (that is why you are not able to use BoxConstraints widget in many cases).
One can read more about the problems of passing constraints in Flutter here - a must read: https://medium.com/flutter-community/flutter-the-advanced-layout-rule-even-beginners-must-know-edc9516d1a2
This work works for me
height: MediaQuery.of(context).size.height,