How to expand container height to max? - flutter

I'm having an issue trying to make one of my containers stretch to max screen height,
home: Scaffold(
backgroundColor: Colors.teal,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: double.infinity,
width: 100,
color: Colors.red,
)
],
),
),
),
I thought by making the height value infinity it would stretch the red container across the entirety of the safe area.
Although the container is invisible unless I put a value in height.

You should use an Expanded widget.
According to the official documentation, An Expanded widget is a widget that expands a child of a Row, Column, or Flex so that the child fills the available space.
Read more about the Expanded widget here: Expanded Widget
class Test extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.teal,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Container(
width: 100,
color: Colors.red,
),
)
],
),
),
);
}
}
OUTPUT

Wrapping the container to Expanded will make its size max like this :
home: Scaffold(
backgroundColor: Colors.teal,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Container(
width: 100,
color: Colors.red,
)
)
],
),
),
),

Related

How expanded widget works in flutter?

I have a simple code which produces design like this
This is my code
This is my code for the design:
class InputPage extends StatefulWidget {
#override
_InputPageState createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BMI CALCULATOR'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: Row(
children: [
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
],
),
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33)),
),
Expanded(
child: Row(
children: [
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
],
),
),
Container(
width: double.infinity,
height: 100,
color: Colors.pink,
)
],
),
);
}
}
Now when I remove the parent expanded widget, I get a design like this:
Here is the code for this design:
class _InputPageState extends State<InputPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BMI CALCULATOR'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Row(
children: [
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
],
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33)),
),
Row(
children: [
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
],
),
Container(
width: double.infinity,
height: 100,
color: Colors.pink,
)
],
),
);
}
}
What is the reason for this? Even if I remove for the parent I have added expanded for the child, so shouldn't it be the same?
ReusableCard:
class ReusableCard extends StatelessWidget{
final Color colour;
ReusableCard({#required this.colour});
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(15),
decoration: BoxDecoration(
color: colour,
borderRadius: BorderRadius.circular(20)
),
);
}
}
Basically The Expanded widget will expand to all of the remaining height the parent widget have,
So you in the first code, in your body inside the column we have 4 widgets
Expanded(
child: Row(
),
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33)),
),
Expanded(
child: Row(
),
),
Container(
width: double.infinity,
height: 100,
color: Colors.pink,
)
So lets say that the height of the parent widget is 1000, the
height of the container at the end is fixed so it will always take 100, so 900 is left
The three expanded widget in the column will take the remaining 900, and because you did not specify any flex property in the Expanded widget all of them will receive same height so 900/3 = 300 for each widget.
in the second code inside the column you have
Row(
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33)),
),
Row(
),
Container(
width: double.infinity,
height: 100,
color: Colors.pink,
)
again assuming the height available is 1000, the container is fixed height of 100 so 900 is left, now the expanded widget will take all of the available height which is 900 because the rows don't have any fixed height.
the Expanded widget inside the Rows will make the card inside them expand to the parent height, but the parent row does not have any height (0 height) so it will expand to this 0 height which is useless.
always keep it in mind that the Expanded will take the height or width from its parent widget.

How to configure a container in flutter to use the same height of an other children in the same row or column

I like to increase the height of the widget "B" so the orange color use the same space like the green color. I have added a code example.
If a added Extended() like Expanded(Container(Text('B'))) the full horizontal space of the screen is used.
If a added Extended() like Column(Expanded(Container(Text('B')))) the full vertical space of the screen is used.
Does someone has a hint?
Thank you in advance!
Gretings
Michael
Problem:
Goal:
Code:
import 'package:flutter/material.dart';
void main() {
runApp(DemoX());
}
class DemoX extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
color: Colors.red,
child: Container(
color: Colors.green,
child: Text('A1\nA2'),
),
),
Container(
color: Colors.orange,
child: Text('B'),
),
],
),
),
),
);
}
}
Screenshot
Code:
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: IntrinsicHeight(
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
color: Colors.green,
child: Text('A1\nA2'),
),
Container(
color: Colors.orange,
child: Text('B'),
),
],
),
),
),
);
}

Flutter position Widget between bottom of screen and safe area

In my app I have a bottomBar which is placed at the bottom right above the SafeArea:
The problem is that I would like to have a white Container at the bottom (red arrow in image) so that for bigger iPhones (where the bottom of the screen IS NOT EQUAL to the safeArea) the empty place in the image if filled white.
For phones where the bottom screen is equal to the safeArea the fillContainerHeight should simply be nil/zero.
This is my setup:
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
// mainAxisSize: MainAxisSize.max,
children: [
SafeArea(
child: Row(
children: [
Expanded(
child: Container(
height: 49,
color: Colors.white,
)),
Container(
height: 49,
child: Image.asset('assets/images/bottomBar.png')),
Expanded(
child: Container(
height: 49,
color: Colors.white,
)),
],
),
),
Container(color: Colors.white) // -> fill container
],
)
Right now the container is not being shown. What is the best way to solve my problem here? I couldn't find anything on this. Let me know if you need any more info!
You could try to use the stack widget like this (the second child (align widget) is positioned above your SafeArea widget):
return Stack(
children: [
SafeArea(
child: Scaffold(
appBar: AppBar(),
body: // Your other widgets here
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
color: Colors.white,
height: MediaQuery.of(context).padding.bottom;,
),
)
],
);
Another option would be to wrap your SafeArea in a Container and give it a white background while setting the top property to false (= meaning the SafeArea will not be applied to the top):
return Container(
color: Colors.white,
child: SafeArea(
top: false,
child: Scaffold(
appBar: AppBar(),
body: // Your other widgets here
),
),
);

Flutter's Flexible Behavior

I want the blue to be full.
But it only spreads up to half.
https://i.stack.imgur.com/UQsiB.png
class TestScene extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
fit: FlexFit.loose,
child: Container(
color: Colors.red,
child: const Text('1'),
),
),
Flexible(
fit: FlexFit.loose,
child: Container(
color: Colors.blue,
child: const Text('1234567890123456789012345678901234567890'),
),
),
],
),
);
}
}
The reverse will also fail.
https://i.stack.imgur.com/rf00I.png
In both cases, it's nice.
https://i.stack.imgur.com/21ORb.png
This is a way ! (To take remain space)
String one='1',two='1234567890123456789012345678901234567890';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
backgroundColor:Colors.white,
body: Row(
mainAxisSize:MainAxisSize.max,
children: <Widget>[
one.length>=two.length ?
Expanded(
child: Container(
color: Colors.red,
child: Text(one),
),
):Container(
color: Colors.red,
child: Text(one),
),
two.length>=one.length ?
Expanded(
child: Container(
color: Colors.blue,
child: Text(two),
),
):Container(
color: Colors.blue,
child: Text(two),
),
],
),
);
}
Or to maintain equal size with colors simply use Expanded in both widgets
Wrap the one that you want to fill the space by Expanded. If you want both red and blue to fill the row, wrap both of them with Expanded and give them their own ratio with the flex property
class TestScene extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Row(
children: <Widget>[
Container(
color: Colors.red,
child: const Text('1'),
),
Expanded(
child: Container(
color: Colors.blue,
child: const Text('1234567890123456789012345678901234567890'),
),
),
],
),
);
}
}

Flutter Layout Row / Column - share width, expand height

I'm still having a bit of trouble with the layouting in Flutter.
Right now I want to have the available space shared between 3 widgets, in a quadrant layout.
The width is evenly shared (this works fine via 2 Expanded widgets in a Row), but now I also want the height to adjust automatically so widget3.height == widget1.height + widget2.height.
If the content of widget3 is larger, I want widget1 and widget2 to adjust their height and vice versa.
Is this even possible in Flutter?
Have a look at IntrinsicHeight; wrapping the root Row should provide the effect you're looking for:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(title: Text('Rows & Columns')),
body: RowsAndColumns(),
),
);
}
}
class RowsAndColumns extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 100.0),
child: IntrinsicHeight(
child: Row(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
Expanded(
child: Column(children: [
Container(height: 120.0, color: Colors.yellow),
Container(height: 100.0, color: Colors.cyan),
]),
),
Expanded(child: Container(color: Colors.amber)),
]),
),
);
}
}
Adjusting the heights in the containers in the column cause the container on the right to resize to match:
https://gist.github.com/mjohnsullivan/c5b661d7b3b4ca00599e8ef87ff6ac61
I think that you can set the height of the row instead, then you only must to set the height of you column containers, and with the crossAxisAlignment: CrossAxisAlignment.stretch the second row will be expand occupying his parent height:
Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Column(
children: [
Expanded(
// If you don't have the height you can expanded with flex
flex: 1,
child: Container(
height: 50,
color: Colors.blue,
),
),
Expanded(
flex: 1,
child: Container(
height: 50,
color: Colors.red,
),
)
],
),
),
Expanded(
child: Container(
color: Colors.yellow,
),
)
],
)
Since IntrinsicHeight is considered relatively expensive, it's better to avoid it. You can use Table with verticalAlignment: TableCellVerticalAlignment.fill in the largest TableCell.
Please note that if you use .fill in all cells, the TableRow will have zero height.
Table(children: [
TableRow(children: [
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
alignment: Alignment.center,
color: Colors.blue,
child: Text('Widget 1'),
),
Container(
alignment: Alignment.center,
color: Colors.green,
child: Text('Widget 2'),
),
],
),
TableCell(
verticalAlignment: TableCellVerticalAlignment.fill,
child: Container(
alignment: Alignment.center,
color: Colors.orange,
child: Text('Widget 3'),
)),
]),
]),
I'm new to flutter. Please correct me if I'm doing something wrong here. I think It can also be achieved using setState((){}) without using IntrinsicHeight.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
double h1 = 100;
double h2 = 200;
double h3;
setState(() {
h3 = h1 + h2;
});
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.only(top: 100.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
children: [
Container(
color: Colors.green,
height: h1,
),
Container(
color: Colors.orange,
height: h2,
)
],
),
),
Expanded(
child: Container(
color: Colors.yellow,
height: h3,
),
)
],
),
),
),
),
);
}
}
Find image here
Code can also be found here: https://gist.github.com/Amrit0786/9d228017c2df6cf277fbbaa4a6b20e83
if you have used the expanded inside Row and facing for full height issue then just wrap the expanded child with Align widget.