I am working on a Flutter project. I'm trying to create a widget like the image below and I can't manage to do it.
So what I'm trying to do, is to create a widget with a Text at the top left (the size of this widget is not constant and depends on the text in it).
I'm trying to align 2 other widgets with the Text:
The Widget 1 is aligned horizontaly and centered with the Text widget and at its right with no space between
The Widget 2's right edge is aligned verticaly with the Text widget's right edge, and is positioned under it (and there is no space between the 2 widgets).
I tried to implement this with Column and Row widgets or with a GridView but I couldn't manage to do so.
Also the overall size of this custom widget has to be shrinked.
Does someone know how to do something like that ?
Thank you.
This works
Container(
width: double.infinity,
height: 300,
color: Colors.grey[200],
child: Column(
children: <Widget>[
Row(
children: [
Flexible(
flex: 2,
child: Container(
height: 200,
color: Colors.blue,
),
),
Flexible(
flex: 1,
child: Container(
height: 100,
color: Colors.green,
),
),
],
),
Row(
children: <Widget>[
Flexible(
flex: 2,
child: Align(
alignment: Alignment.centerRight,
child: Container(
width: 150,
height: 100,
color: Colors.orange,
),
),
),
Flexible(
flex: 1,
child: Container(),
),
],
),
],
),
),
Related
I want to make children use flexible sizes
how can i set the size of the child inside the row? can you guys help me? and find the error constraint
anyone help me
return SafeArea(
child: Column(
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Container(
color: Colors.lightBlue,
child: Row(
children: [
Expanded(
flex: 5,
child: Container(
color: Colors.green,
),
),
Expanded(
flex: 5,
child: Container(
color: Colors.blue,
),
)
],
),
)
],
),
)
],
),
);
To place children in a row you can use Flexible widget. The value of flex defines how much space each child should take. In the example that you provided.. Both children will be equally spaced since you gave flex value 5 for both.
return Scaffold(
body: Center(
child: SizedBox(
height: 50,
child: Row(
children: [
Flexible(
flex: 5,
child: Container(
color: Colors.red,
)),
Flexible(
flex: 5,
child: Container(
color: Colors.green,
)),
],
),
),
),
);
If you change the flex value to 1 and 5.. Now the total divisions will be 6 and out of that the first child will take 1 part and the second child will take 5 parts like below
return Scaffold(
body: Center(
child: SizedBox(
height: 50,
child: Row(
children: [
Flexible(
flex: 1,
child: Container(
color: Colors.red,
)),
Flexible(
flex: 5,
child: Container(
color: Colors.green,
)),
],
),
),
),
);
Also if you use a singleChildScrollView and an expanded inside that it then the expanded widget has no bounds so it will throw an error. So wrapping the Expanded with a SizedBox with a specific width will give you expected results.
EDIT
To have a SingleChildScrollView with dynamic content in the row you can do this
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisSize : MainAxisSize.min,
children:[
SizedBox(
width: 100,//this is important since its a row and the row will take full width and throw an error.
child: Image.asset(""),
),
//Another SizedBox or Text or any widget..
]
)
)
I have these three containers. That the first one needs to grow to cater for the children that will be in it. The second one could have a fixed height say a flex factor of 1, while the third one has a fixed height too say flex of 2. The whole of this screen can be scrollable. It actually has to be scrollable since the children of the first container can be a lot.
Note: the children of the first container will have a fixed height, the container will house a listview or column which will have fixed height children, say containers each of 50.0. How do I achieve this, especially the 'growability' of the first container, while maintaining the heights of the other containers.
What I have currently is
SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: ListView(
children: [
Flexible(
flex: 1,
child: Container(
color: Colors.blueAccent[200],
child: Column(children: [
Container(
height: 100.0,
color: Colors.greenAccent[200],
),
Container(
height: 100.0,
color: Colors.purpleAccent[200],
),
Container(
height: 100.0,
color: Colors.orangeAccent[200],
)
]),
)),
Expanded(
flex: 1,
child: Container(
color: Colors.redAccent[100],
),
),
Expanded(
flex: 1,
child: Container(
//height: 120.0,
color: Colors.redAccent[400],
),
),
],
),
),
),
Which just brings up lots and lots of errors, does not matter how I lay it out using flexibles and Expanded widgets. Again, I don't need the first container to scroll internally, it should grow according to the number of children in it, while the rest of the two containers maintain their heights.
You can not user Expanded or Flexible inside a scrollable widget since the child of Expanded will then get a height of infinity and the height of the child of Flexible will not get its parents height to compare with.
You can set the height of the bottom two containers based on the height of the screen.
SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: ListView(
children: [
Container(
color: Colors.blueAccent[200],
child: Column(
children: [
Container(
height: 100.0,
color: Colors.greenAccent[200],
),
Container(
height: 100.0,
color: Colors.purpleAccent[200],
),
Container(
height: 100.0,
color: Colors.orangeAccent[200],
)
],
),
),
Container(
// 33 % of the screen height
height: .33 * MediaQuery.of(context).size.height,
color: Colors.redAccent[100],
),
Container(
// 33 % of the screen height
height: .33 * MediaQuery.of(context).size.height,
color: Colors.redAccent[400],
),
],
),
),
),
I use this simple widget in my Flutter app:
FlatButton(
child: Column(
children: <Widget>[
Image.asset(assets, height: 40, width: 40),
Text('Title'),
//my color line
Container(
height: 5,
width: ?,
color: Colors.blue[800],
)
],
)
)
I need color line (in buttom), with width match parent. but I don’t know how to do it.
Container(
height: 5,
width: double.infinity,
color: Colors.blue[800],
)
Use IntrinsicWidth
FlatButton(
child: IntrinsicWidth(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Image.asset(assets, height: 40, width: 40),
Text('Title'),
//my color line
Container(
height: 5,
width: ?,
color: Colors.blue[800],
)
],
))
)
Some cheatsheet
Two ways of doing this
ConstrainedBox:
It Creates a widget that imposes additional constraints on its child, which internally uses SingleChildRenderObjectWidget to add constraints over the child widget.
ConstrainedBox(
constraints:
const BoxConstraints(minWidth: double.infinity, maxHeight: 10),
child: Container(
color: Colors.blue,
),
),
SizedBox:
SizedBox simply creates a box with a given width/height and doesn't allow the child to go beyond given dimensions. It also used SingleChildRenderObjectWidget to decide the child render area
SizedBox(
width: double.infinity,
height: 5,
// height: double.infinity,
child: Container(
color: Colors.blue,
),
),
Container in a Column with no child will always expand. if you do add a child it will wrap it.
Also if you don't constrain your Column in the button it will also grow to full available height.
My suggestion to you is instead of putting an empty Container in your button's Column, rather wrap the button with a Container and give it a bottom border. This will give you your colored line on the bottom.
Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(width: 5, color: Colors.blue[800]),
),
),
child: FlatButton(
onPressed: () {},
child: Column(
mainAxisSize: MainAxisSize.min, // prevent Column to expand full height
children: <Widget>[
Icon(Icons.cake, size: 40),
Text('title'),
],
),
),
),
Image of the problem, shown as colored rectangles
I want the first child of Column to be Flexible and the second to take up the entire remaining space. Apparently, this does not work.
I'm now aware that this is the expected behavior. I would appreciate a workaround.
I've tried using FittedBox on the first child instead of Flexible, but it didn't work as the content of the first child has unbounded width.
SizedBox(
height: 300,
width: 50,
child: Container(
color: Colors.black,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
child: Container(
height: 100,
color: Colors.red,
),
),
Expanded(
child: Container(
color: Colors.blue,
),
),
],
),
),
);
I want to make the first child (i.e. A TextField) Flexible so that if the height gets too small, there are no ugly yellow-black overflow bars.
Update:
Below image shows what I really want to do, but it has the overflow issue because the first child isn't flexible.
shows what happens when I do use Flexible.
I'm using AnimatedContainer to change the height. I prefer not to use SizeTransition if possible.
Just replace your code with the next one (flexes ratio can be adjusted to the right one):
SizedBox(
height: 300,
width: 50,
child: Container(
color: Colors.black,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
flex:1
child: Container(
height: 100,
color: Colors.red,
),
),
Flexible(
flex:10
child: Container(
color: Colors.blue,
),
),
],
),
),
);
I have a stack widgets with two widgets inside.
One of them draws the background, the other one draws on top of that.
I want both widgets to have the same size.
I want the top widget, which is a column, to expand and fill the stack vertically to the size that is set by the background widget.
I tried setting the MainAxis mainAxisSize: MainAxisSize.max but it didn't work.
How can I make it work?
Use Positioned.fill
Stack(
children: [
Positioned.fill(
child: Column(
children: [
//...
],
),
),
//...
],
);
More info about Positioned in Flutter Widget of the Week
How does it work?
This is all about constraints. Constraints are min/max width/height values that are passed from the parent to its children. In the case of Stack. The constraints it passes to its children state that they can size themselves as small as they want, which in the case of some widgets means they will be their "natural" size. After being sized, Stack will place its children in the top left corner.
Positioned.fill gets the same constraints from Stack but passes different constraints to its child, stating the it (the child) must be of exact size (which meant to fill the Stack).
Positioned.fill() is the same as:
Positioned(
top: 0,
right: 0,
left: 0,
bottom:0,
child: //...
)
For even more examples and info: How to fill a Stack widget and why? and Understanding constraints.
You can try wrapping the Column with a positioned widget. Set top to 0 and bottom to 0. This will make the column fill the stack vertically.
sample code:
Stack(
children: <Widget>[
// Background widget rep
Container(
color: Colors.pink,
),
Positioned(
top: 0,
bottom: 0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('madonna'),
Text('flutter'),
],
),
)
],
)
I think you could wrap you column in a container like this:
Container(
height: double.infinity,
width: double.infinity,
child: Column()
),
The accepted answer did not answer my issue completely. So, I put my code here in case you have a similar issue.
class NoContentView extends StatelessWidget {
const NoContentView({Key? key, required this.message}) : super(key: key);
final String message;
#override
Widget build(BuildContext context) {
return Expanded(
child: Stack(
children: [
Positioned.fill(
child: FittedBox(
child: const Image(image: AssetImage(AppImages.noReceiptsWeb), fit: BoxFit.fitWidth),
),
),
MessageView(message: message),
],
),
);
}
}
In my case, I thought that I needed to expand the container in the light blue color with an expanded widget inside the stack widget.
Problems arose, especially since I was adding the stack widget in the column widget, and the way to make the container double.infinity dimensions I definitely had a problem with the vertical axis.
In the end, I managed to show it like this photo...
Column(
children: [
//filter
Container(
color: orange,
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
child: Text(
'All',
style: getRegular(color: white.withOpacity(.6)),
),
),
Container(
color: white.withOpacity(.6),
width: 1,
height: 50,
),
Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 10, 0),
child: Text(
'Ready',
style: getRegular(color: white.withOpacity(.6)),
),
),
freeh(),
Container(
color: white.withOpacity(.6),
width: 1,
height: 50,
),
],
),
Row(
children: [
Icon(
filter,
color: white.withOpacity(.7),
size: 20,
),
Text(
'FILTER',
style: getLight(
color: white.withOpacity(.7),
),
),
freeh(),
],
),
],
),
),
Expanded(
child: Stack(
alignment: Alignment.topLeft,
children: [
Container(
color: lightBlue, //here to use map>>>>
),
Container(
height: 35,
width: 120,
margin: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: primary,
borderRadius: BorderRadius.circular(20),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Icon(
FontAwesomeIcons.listUl,
color: white.withOpacity(.8),
size: 20,
),
Text(
'List View',
style: getRegular(color: white.withOpacity(.8)),
)
],
),
),
],
),
)
],
),