Fit of individual children in Stack - dart

I have a Stack widget with some children. One of those children is an Align which has a Container child which has a Column child. This Column has some children. Now, in my Stack, the Column is way bigger than it should be (it fills the complete screen) although a third of that space would be enough. I'd like to know how I can use something like Flexible so I can use the fit property to tighten up the space. Is this possible?
Here is a representation of my code:
new Stack(
children: <Widget>[
new Container(...),
new Align( // This takes up way more space than needed!
alignment: new Alignment(1.0, 1.0) // This widget should be displayed at the bottom
child: new Container(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget> [
new Container(child: new Center(child: new Text("text"))),
new Row(children: [...]),
new Row(children: [...]),
new Row(children: [...]),
new Row(children: [...]),
]
)
)
)
]
)
I tried playing around with the fit property but without any luck.

By default, Column has mainAxisSize defaulting to MainAxisSize.max.
Which means that Column will take all the available height.
In your case, you don't want that. So you can set that value to MainAxisSize.min, which will do the opposite : fit it's children.
The end result is :
child: new Stack(
children: <Widget>[
new Container(...),
new Align(
alignment: Alignment.bottomCenter,
child: new Container(
color: Colors.purple,
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[new Text("foo"), new Text("hello world")],
),
),
)
],
),

Related

How to Center ListView?

I have Column but issue is if screen very small height there is error:
BOTTOM OVERFLOWED BY 5.0 PIXELS
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CenterBoxText(),
SizedBox(height: 1),
RaisedButton(
child: Text(‘Example’),
),
],
),
I have try replace Column with ListView and this stop error. But now on large screen Widget are display from top and not in center. Because ListView no have mainAxisAlignment: MainAxisAlignment.center.
How to solve?
Thanks!
Try wrapping your Column widget with SingleChildScrollView widget, It will provide the ability to scroll.
Like this :
SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CenterBoxText(),
SizedBox(height: 1),
RaisedButton(
child: Text(‘Example’),
),
],
),
),
If you are having problems with the Column creating an overflow, then it is probably overflow in the vertical axis. ListView enables scrolling in the vertical axis and allows the overflow pixels to be below the viewing screen. That is why ListView works for you and Column doesn't. Since you want Column, then you just need to wrap the Column in an Expandable so the Column fits within the available space.
Here is a complete example:
import 'package:flutter/material.dart';
class ColumnTest extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
//CenterBoxText(),
SizedBox(height: 1),
RaisedButton(
child: Text('example'),
),
],
),
))
],
),
);
}
}
Replace your Column with ListView.
In your ListView - add - shrinkWrap: true, then wrap your ListView with Center widget.

How do I use different crossAxisAlignment for different rows on the same column?

I want to align two pieces of text differently, where each piece of text is in a different row but in the same column.
Here's a crudely illustrated structure for this widget
As you can see "info text" is next to "video duration", but I want it at the top, and I want to keep "video duration" at the bottom at all times.
I tried using alignment settings but I don't know why one doesn't seem to be working (I commented it in the code below)
class MiniVideoCell extends StatelessWidget {
final lesson;
MiniVideoCell(this.lesson);
#override
Widget build(BuildContext context) {
return new Column(
children: <Widget>[
new Container(
padding: new EdgeInsets.all(12.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
new Column(
children: <Widget>[
new Image.network(
lesson.imageUrl,
width: 150.0,
),
],
),
new Column(
crossAxisAlignment: CrossAxisAlignment.start, //meant to align elements to the left - seems to be working
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.start, //trying to bring this text up, not working
children: <Widget>[
new Text("info text"),
],
),
new Row(
children: <Widget>[
new Text("video duration"),
],
),
],
),
],
),
),
new Divider(),
],
);
}
}
You can try to set your mainAxisAlignment property of your Column widget to MainAxisAlignment.spaceBetween. This would put all available space between your Row widgets.
new Column(
crossAxisAlignment: CrossAxisAlignment.start, //meant to align elements to the left - seems to be working
mainAxisAlignment: MainAxisAlignment.spaceBetween, // Add this line
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.start, //trying to bring this text up, not working
children: <Widget>[
new Text("info text"),
],
),
new Row(
children: <Widget>[
new Text("video duration"),
],
),
],
)
And also we need to specify the height and width of our Container widget like this:
Container(
padding: EdgeInsets.all(12.0),
width: double.infinity, // Added width
height: 124.0, // Set your preferred height
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
...
Output would look like this:
Here is the partial code:
Column(
children: [
Container(
padding: EdgeInsets.all(12.0),
width: double.infinity, // Added this
height: 124.0, // Set your preferred height
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Column(
children:[
Container(
color: Colors.blue,
width: 150.0,
height: 100.0, // Assuming that the height of the thumbnail is 100 pixels
)
]
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, // Place all available space between the children
children:[
Row(
mainAxisAlignment: MainAxisAlignment.start, //trying to bring this text up, not working
children: <Widget>[
new Text("info text"),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start, //trying to bring this text up, not working
children: <Widget>[
new Text("video duration"),
],
),
]
)
]
),
),
Divider(),

Right alignment without resizing parent

I am trying to align something to the right without resizing it's parent. So technically the box size should be dependent on the text object, and the icon should be aligned to the right.
return new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text("this is a test string"),
new Align(
alignment: Alignment.topRight,
child: new Icon(Icons.speaker_notes),
),
]);
Once the alignment is set to Alignment.topRight the box gets drawn with the full screen width. I understand why it gets rendered like this, but can't think of a solution either. Any ideas?
You could try something like this:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Align(
alignment: Alignment.topLeft,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
new Text("this is a test string"),
new Icon(Icons.speaker_notes),
]),
),
);
}
Result

How to align a Column's child to the bottom

I'm trying to build a generic home page and I want to align the last child of my column (which contains all the widgets for the page) to the bottom of the screen but the widget wrapped in the Align is not moving. The following is what makes the most sense to me:
Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
ChildA(),
ChildB(),
Align(
alignment: Alignment.bottomCenter,
child: BottomAlignedChild()
)
]
)
What am I doing wrong?
You can use Expanded to make the last widget expand to the whole remaining space.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My Layout',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Align Bottom Demo"),
),
body: new Column(children: <Widget>[
new Text("Text 1"),
new Text("Text 2"),
new Expanded(
child: new Align(
alignment: Alignment.bottomCenter,
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Icon(Icons.star),
new Text("Bottom Text")
],
)))
]),
);
}
}
Here is the result
Another approach is using Spacer():
...
Column(children: [Text1, Text2, Spacer(), YourBottomWidget()]),
...
I have always used Spacer for these kind of cases in Column or Row. Spacer takes up all the available space between two widgets of Row/Column.
For given example, you can try following
Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
ChildA(),
ChildB(),
Spacer(),
BottomAlignedChild()
]
)
There are multiple ways of doing it.
Use Spacer:
Column(
children: <Widget>[
TopContainer(),
Spacer(), // <-- Spacer
BottomContainer(),
],
)
Use mainAxisAlignment:
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // <-- spaceBetween
children: <Widget>[
TopContainer(),
BottomContainer(),
],
)
Combine Expanded and Align:
Column(
children: <Widget>[
TopContainer(),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: BottomContainer(),
),
),
],
)
Screenshot (same for all)
If you are flexible to change column to a stack, you can do the following.
body: Container(
child: Stack(children: <Widget>[
Text('Text 1'),
Text('Text 2'),
Align(
alignment: Alignment.bottomCenter,
child: Text(
"Text in bottom",
),
),
]),
),
You can try wrapping the widgets which needs to be at the top inside another Column widget, thereby making the root widget containing only two children. 1st child containing all the widgets which need to be aligned at the top and the 2nd child containing widget which is to be placed at the bottom. Now you use mainAxisAlignment: MainAxisAlignment.spaceBetween to align 1st child to the top and second to the bottom.
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Column(
children: <Widget>[
ChildA(),
ChildB(),
]
),
BottomAlignedChild(),
]
);

Flutter column doesn't expand

I am a complete newbie in Flutter, but I already like it.
The question is:
why is the column not expanding to the full height?
code is on gist.github
Using CrossAxisAlignment.stretch works for me:
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text("Some title"),
Text("Address"),
Text("Description")
],
),
A Column widget is flexible - it will try to take up as much space as it needs but no more. If you want it to take up all availible space, then wrap it in an Expanded widget.
createChildren() {
return [
Image.network(
testImg,
height: imageSize,
width: imageSize,
),
Padding(padding: EdgeInsets.only(left: 16.0)),
Expanded(child:
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
boldText("Some title"),
Text("Address"),
Text("Description")
],
),
),
];
}
Wrapping the column with a row with MainAxisSize.max
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Column(
children: <Widget>[
_someWidget(),
_someWidget(),
_someWidget(),
],
),
],
)
Don't use flex=1 inside Column, here you can see example
children: [
MyWidget(),
Expanded(
child: MyWidget(),
),
MyWidget(),
],
Based on your layout I assume that your Column is nested inside a Row. Wrap your Row with IntrinsicHeight and your Column will automatically expand its height to be the same as the Row's tallest child:
IntrinsicHeight(
child: Row(
children: [
Container(width: 40, height: 40, color: Colors.blue),
// tallest child
Container(width: 40, height: 60, color: Colors.blue),
// height will be 60
Column(
...
),
],
),
)
You can wrap the Column inside an infinite width SizedBox.
SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [ ... ]
)
)
The above code snippet will place the children at the center of the SizedBox. It'll work especially well if you want to use a Column as the body of your Scaffold. In that case children will show up at the center of the screen.
The code linked in the question is no longer available, so I can't give you a full working example for your case. However, one thing that will likely work is using mainAxisAlignment as follows:
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
Text("Some title"),
Text("Address"),
Text("Description")
],
),
(mainAxisSize: MainAxisSize.max is actually the default value, butthis only works if you do not set it to MainAxisSize.min, so I included it here.)
Setting mainAxisAlignment to MainAxisAlignment.spaceAround or MainAxisAlignment.spaceEvenly will also expand the column, but spacing between/around children will be handled differently. Try it out and see which you like best!
This will cause the column to take all the space it can - if it still doesn't expand then that is due to its parent widget, and we can no longer access the code so I can't speak to that.

Resources