Flutter - Padding using empty Containers? - flutter

I have a column that stretches from the top of my screen to the bottom, inside that column are two rows each with three buttons.
What's the best/proper way to adjust the vertical spacing between these two rows?
Currently I'm using Expanded's with an empty child container to add gaps between children of the column, so I have a 10% 'gap' between the top of the page and the first row and another 10% 'gap' between the two rows
This doesn't feel quite right and I seem to be limited to XX% amounts of padding, I want to try and avoid specific pixel amounts so the layout remains consistent regardless of screen size
Column(
children: <Widget>[
Expanded(flex: 1, child:Container()),
Expanded(flex: 3, child:
Row(children: <Widget>[
Expanded(child: _navButton(Icons.person, "User", ()=>print("User"))),
Expanded(child: _navButton(Icons.insert_drive_file, "Formulation", ()=>print("Formulation"),)),
Expanded(child: _navButton(Icons.lightbulb_outline, "Devices", ()=>print("Devices"),)),
],)),
Expanded(flex: 1, child:Container()),
Expanded(flex: 3, child:
Row(children: <Widget>[
Expanded(flex: 3, child: _navButton(Icons.settings, "Settings", ()=>print("Settings"), iconColour: Colors.blueGrey)),
Expanded(flex: 3, child: _navButton(Icons.camera_alt, "Photos", ()=>print("Photos"),)),
Expanded(flex: 3, child: _navButton(Icons.cancel, "Exit", ()=>print("Exit"), iconColour: Colors.redAccent)),
],
)),
],
)

Instead of Expanded, you can use Spacer. It is the same as an Expanded with an empty Container.
Row(
children: <Widget>[
Text('Begin'),
Spacer(), // Defaults to a flex of one.
Text('Middle'),
// Gives twice the space between Middle and End than Begin and Middle.
Spacer(flex: 2),
Text('End'),
],
)
You can also use a SizedBox for spacing in DIP:
Row(
children: <Widget>[
Text('Begin'),
const SizedBox(width: 42),
Text('Middle'),
],
)
Another one is Flexible, which is similar to Expanded but works with min/max size:
Row(
children: <Widget>[
Text('Begin'),
Flexible(
child: ConstrainedBox(constraints: const BoxConstraints(maxWidth: 100.0)),
),
Text('Middle'),
],
)

Related

Button within Table within Gridview within Sizedbox or Flex is not clickable dependent on other table rows - Flutter

I am rendering a standard Table inside a GridView, inside a Flex inside a Row. The 2nd row of the table includes a Button.
When the contents of the first row of the table are above a certain size the clickable region of the button begins to cut off, missing entirely over a certain size.
Note: this is using Flutter Web, I have not tested on Mobile/Desktop.
I have created a minimal reproducible example in an attempt to isolate all logic.
Widget _render() {
return Row(mainAxisSize: MainAxisSize.max, children: [
SizedBox(
width: 900,
height: 900,
child: GridView.count(
crossAxisCount: 2,
children: <Widget>[
Table(border: TableBorder.all(), children: <TableRow>[
TableRow(
children: <Widget>[
TableCell(
child: Text(''),
),
TableCell(
child: SizedBox(
height:
440, //The clickable region of the button begins to be cut off around 430, and stops altogether by 450
))
],
),
TableRow(children: <Widget>[
TableCell(
child: Text(""),
),
TableCell(
child: TextButton(
onPressed: () => {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Hi Button"))),
},
child: Text("Hi"))),
])
]),
],
),
),
]);
}
What is causing this effect? I am assuming it is some interaction between the visible container and the Table.
Edit: as suggested by #pskink rendered with debugPaintSizEnabled flag which highlights the problem perfectly. However; how would you fix?

How to force a ListView not to expand more than other widgets in a row (Flutter)

I'm struggling with this and can't describe it as well as I should on search engine, so here's my problem: I have a Row containing two Expanded with flex: 5 aiming to have two width-equal cells; inside the first cell, I have a Column (containing a Table and a Button); inside the second cell I have a Column (containing a ListView and a Button); I'd like to force the ListView to become scrollable once its content gets higher than first cell's intrinsic height, so second cell's height never gets higher than first cell's height.
Row(
children: [
Expanded(
flex: 5,
child: Column(
children: [
DataTable(),
ElevatedButton()
]
), // Column
), // Expanded
Expanded(
flex: 5,
child: Column(
children: [
ListView(),
ElevatedButton()
]
), // Column
) // Expanded
]
) // Row
I lost myself trying stuff with shrinkWrap: true on the ListView, IntrinsicHeight() around the Row, etc.
Thank you for your help!
EDIT:
Solution I found is going the hard way by listening to first cell's size changes and to set its height as second cell's height (thanks to this Medium link). Even tho I'd rather go for a cleaner way, it seems to work like it should.
This is what my code currently looks like:
Row(
children: [
Expanded(
flex: 5,
child: WidgetSize(
onChange: (size) {
if (size != null)
setState(() => heightOfTable = (size as Size).height);
},
child: Column(
children: [
DataTable(),
ElevatedButton()
]
), // Column
), // WidgetSize
), // Expanded
Expanded(
flex: 5,
child: Container(
height: heightOfTable,
child: Column(
children: [
ListView(),
ElevatedButton()
]
), // Column
), // Container
) // Expanded
]
) // Row
If you've got a better idea, please let me know! :)
I think you can try wrapping the ListView inside a Container and give a suitable height and `width.
Row(
children: [
Expanded(
flex: 5,
child: Column(
children: [
DataTable(),
ElevatedButton()
]
), // Column
), // Expanded
Expanded(
flex: 5,
child: Column(
children: [
Container(
height:,
width:,
child: ListView()),
ElevatedButton()
]
), // Column
) // Expanded
]
) // Row

How to add space between Rows in flutter?

main issue is i want to add some space between Rows and this Rows are children of SingleChildScrollView, my widget tree :
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
// first row with 3 column
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(),
Container(),
Container(),
],
),
Row(
// second row also with 3 column ans so on
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(),
Container(),
Container(),
//Row( third row also with 3 column ans so on
//Row( fourth row also with 3 column ans so on
// ....
],
),
],
),
),
i got the following out put :
so how to add more space to the widget SingleChildScrollView , so to expect that mainAxisAlignment:MainAxisAlignment.spaceBetween put some space between the rows , or how simply add a space between rows?
Things like SizedBox work great if you are happy with a fixed pixel gap. Spacer is another alternative, and is flexed, which may or may not be what you want, depending on what you have it nested under. If you prefer to work with relative sizes, I can also recommend FractionallySizedBox, which operates on a percentage of the area, and works great for responsive designs. If you wanted to have a 5% vertical gap, for example, you could express this as:
FractionallySizedBox(heightFactor: 0.05),
try between the rows
SizedBox(height:20),
final code
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
// first row with 3 column
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(),
Container(),
Container(),
],
),
SizedBox(height:20),
Row(
// second row also with 3 column ans so on
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(),
Container(),
Container(),
//Row( third row also with 3 column ans so on
//Row( fourth row also with 3 column ans so on
// ....
],
),
],
),
),
Insert a Padding widget.
Row(...),
Padding(padding: EdgeInsets.only(bottom: 10),
Row(...)
You can also use Spacer( ... . )
For me Padding is ok
Row(...),
SizedBox(width:20). // If want horizontal space use width for vertical use height
Row(...)
you can use SizedBox b/w Rows

Flutter: how to center a child, but set a limit on how big it can grow on one side of the margin

I have a home/login screen which is made up of a column that fills the entire screen like so:
Column(
children: <Widget>[
Expanded(
child: Container(
child: Logo(),
),
),
showThis ? This() : That(),
],
),
The second child of the column is dynamic and can have different heights, and this screen will have inputs so the keyboard will also affect the height.
I want to center Logo() vertically within the container when it's small (e.g. when keyboard is active), but limit how much the 'top margin' is able to grow, so that when the keyboard is hidden and This()/That() is small enough, Logo() will be in a static position on the screen, say 150 from the top (no longer centred vertically).
One method I have tried was using 2 empty Expanded() above and below Logo() and wrapping the top part in a ConstraintedBox(), but I am not able to get it to behave correctly.
Have you tried with Center() and also if you wanna in a specific position use Stack, for example
Stack(
children: <Widget>[
showThis(),
Positioned(top: 150, child: Logo())
],
)
This is what ended up working for me:
Column(
children: <Widget>[
Expanded(
child: Column(
children: <Widget>[
// constrain top spacing with a max height
Flexible(child: Container(height: 160)),
_logo(),
Spacer(),
],
),
),
_bottomWidget(),
],
),

How can I fill whole free place in a column with a children widget with required size property?

I have an UI in Flutter that has a simple circular chart with some text.
This circular chart (https://pub.dev/packages/flutter_circular_chart) has a required size property. So, we must define its size, but in this way it won't be responsive for all UI screen sizes, it does not fit the whole space I'd like to.
So, e.g. I'd like to set its size to also cover the space annotated with blue:
Is it possible to set its size dynamically to fit whole free space in the column?
I tried expaned, fittedbox with double.infinity size parames etc. but neither of them helped.
My code:
Widget _buildChart() {
return Expanded(
child: Container(
color: Colors.green,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
AnimatedCircularChart(
duration: Duration(milliseconds: 0),
key: _chartKey,
size: const Size(140.0, 140.0),
chartType: CircularChartType.Radial,
percentageValues: true,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_buildText(
'${AppLocalizations.of(context).localize("free")}: $freeCount',
Colors.white),
_buildText(
'${AppLocalizations.of(context).localize("busy")}: $busyCount',
Theme.of(context).buttonColor),
],
)
],
),
),
);
}
Would you be so kind to help me to solve this? How can I make its size responsive? Is it possible at all?
Wrap your AnimatedCircularChart in FittedBox which is further wrapped in Expanded and you don't have to deal with Size anymore. No matter what size you provide, it will always give you the maximum space left.
Expanded( // add this
child: FittedBox( // and add this
child: AnimatedCircularChart(
key: Key("chart_key"),
duration: Duration(milliseconds: 0),
size: Size(1, 1), // no matter even if it is 1, it will take up all remaining space
chartType: CircularChartType.Radial,
percentageValues: true,
initialChartData: data,
),
),
)
Full code:
Widget _buildChart() {
return Expanded(
child: Container(
color: Colors.green,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded( // add this
child: FittedBox( // and add this
child: AnimatedCircularChart(
key: Key("chart_key"),
duration: Duration(milliseconds: 0),
size: Size(1, 1), // no matter even if it is 1, it will take up all remaining space
chartType: CircularChartType.Radial,
percentageValues: true,
initialChartData: data,
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text("Free: 14"),
Text("Busy: 31"),
],
)
],
),
),
);
}
Update:
If you are talking about the remaining space above the ring on bigger screen, then it is because of the ring ability to remain circular in shape, so it can't really go beyond that. I have created a small video recording to show you the effect. And I have used size: 1.
Use the LayoutBuilder class for that.
The layoutbuilder class allows you to give a defined height depending on the parent widget constraints. For example you could say that the chart height is 40% of the available height of the parant widget.
For further responsiveness (screen rotation etc.) check out MediaQuery