Expanding a widget horizontally inside column - flutter

I'm facing some problem by composing layout of my App.
My widget at the end sould look like this
This is my code
Row(
mainAxisSize: MainAxisSize.max,
children: [
Column(
children: [
// Widget A
SizedBox(
height: widget.screenHeight * 0.9,
child: AspectRatio(
aspectRatio: 16 / 9,
child: Container(
color: Colors.red,
),
),
),
// Widget B
Container(
height: widget.screenHeight * 0.1,
color: Colors.green,
)
],
),
// Widget C
Expanded(
child: Container(
color: Colors.pink,
),
)
],
)
I want Widget A to occupy 90% of screen height and mantain a 16/9 aspect ratio, Widget B to occupy remaining 10% height and have the same width of his sibling, and Widget C to fill remaining space
With that code, Widget A and Widget C are showed correctly, but widget B doesn't fill his space as i expect.
What's wrong?

Column(
children: [
Expanded(
child: Row(
children: [
Expanded(
flex: 2,
child: Column(
children: [
Expanded(
flex:4,
child: Container(
color: Colors.yellow,
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.blue,
),
)
],
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.green,
),
),
],
),
)
],
),
you have to play with the expanded widget

Related

how can i set the size of the child inside the row?

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..
]
)
)

Flutter Alignment Containers

So I'm working on my first Project. Basically I want to alignment 4 containers equally. they should have same size H/W so i could scroll on them whenever extra data has been put into them later.....
Here's my Code
Widget build(BuildContext context) {
return Center(
child: Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
children: [
Row(
children: [
VerticalText1(),
DoBuilder(),
],
),
Column(
children: const [
SizedBox(
width: 10,
)
],
),
Column(
children: [
DecideBuilder(),
],
),
],
),
Row(
children: const [
SizedBox(
height: 10,
)
],
),
Row(
children: [
Row(
children: [
VerticalText2(),
DelegateBuilder(),
],
),
Column(
children: const [
SizedBox(
width: 10,
)
],
),
Align(
alignment: Alignment.bottomLeft,
child: DeleteBuilder(),
),
So I'm working on my first Project. Basically I want to alignment 4 containers equally. they should have same size H/W so i could scroll on them whenever extra data has been put into them later.....So I'm working on my first Project. Basically I want to alignment 4 containers equally. they should have same size H/W so i could scroll on them whenever extra data has been put into them later.....
for me I'm also a beginner in flutter but I know something that if you want actual size for container and you want it to be some kind of responsive you have 2 ways to do that:
first you can use:
(Mediaquery).of(context).size.width or
(media.query).of(context).size.height
that will give you the size of your screen and you can use as much as you need from it for each container for example:
Container(
child:,
width: (MediaQuery.of(context).size.width / 2))
that will give you half of your screen width what ever the device run the app the size will be the same for the screen size
and other way you can use expanded widget:
put every container in expanded widget and give the flex parameter value of one
here is an example:
Row(children:[
Expanded(flex:1,child:Container()),
Expanded(flex:1,child:Container()),]),
expanded will sum the flexes and will divide the space of the screen on element all equal repeat the above code in single Column has 2 Rows and I hope your code will work as you want
Instead of row and column, you should try with the GridView otherwise you can try with media query height and width.
GridView.builder(
itemCount: 4,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (BuildContext context, int index) {
return new Card(
child: Container(
color: Colors.green,
child: Center(child: Text("$index"),),
),
);
},
)
And Using Column and row
idget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width-20;
return Scaffold(
appBar: AppBar(
title: Text("widget.title"),
),
body: Stack(
children: [
Column(
children: [
Expanded(
child: Row(
children: [
Container(
height: height / 2,
width: width/2,
color: Colors.green,
),
SizedBox(width: 10,),
Container(
height: height / 2,
width: width / 2,
color: Colors.green,
)
],
),
),
SizedBox(height: 10,),
Expanded(
child: Row(
children: [
Container(
height: height / 2,
width: width / 2,
color: Colors.green,
),
SizedBox(width: 10,),
Container(
height: height / 2,
width: width / 2,
color: Colors.green,
)
],
),
),
],
),
Center(
child: Padding(
padding: const EdgeInsets.only(right:10.0),
child: CircleAvatar(child: Icon(Icons.home),),
),
)
],
),
);
}
Output:

Row with a vertical picture and a horizontal picture with minimum white space?

I am trying to lay out a List of images containing a mix of portrait and landscape images and I would like to minimize white space. For now, I have a column whose children are rows whose children are Flexible whose child are Images:
class MyHomePage extends StatelessWidget {
MyHomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
children: [
Flexible(
child: Image.network(
'https://via.placeholder.com/400x600',
),
),
SizedBox(
width: 8,
),
Flexible(
child: Image.network(
'https://via.placeholder.com/400x600',
),
),
],
),
SizedBox(
height: 8,
),
Row(
children: [
Flexible(
child: Image.network(
'https://via.placeholder.com/600x400',
),
),
SizedBox(
width: 8,
),
Flexible(
child: Image.network(
'https://via.placeholder.com/600x400',
),
),
],
),
SizedBox(
height: 8,
),
Row(
children: [
Flexible(
child: Image.network(
'https://via.placeholder.com/400x600',
),
),
SizedBox(
width: 8,
),
Flexible(
child: Image.network(
'https://via.placeholder.com/600x400',
),
),
],
),
SizedBox(
height: 8,
),
Row(
children: [
Flexible(
child: Image.network(
'https://via.placeholder.com/600x400',
),
),
SizedBox(
width: 8,
),
Flexible(
child: Image.network(
'https://via.placeholder.com/400x600',
),
),
],
),
],
),
),
),
),
);
}
}
This example project demonstrates all the scenarios I want my layout to handle.
So in an app, I get the following:
So as you can see, when a row contains a portrait and a landscape image, the shortest image has a lot of space above and below. And I would like to lay out my images so that the cells of the row are not the same width, but their widths adapt so that the shortest image gets taller and the tallest image gets shorter and they both occupy the full height of the row, without messing with their respective aspect ratios of course.
How can I do that?
By the way, I put together a sample project with the simplest version of my problem here.
have you considered using this package?
Update
if you don't want to use a package, you might try something like this:
final List<Widget> _images = [
Image.network('https://via.placeholder.com/400x600'),
Image.network('https://via.placeholder.com/400x600'),
Image.network('https://via.placeholder.com/600x400'),
Image.network('https://via.placeholder.com/600x400'),
Image.network('https://via.placeholder.com/400x600'),
Image.network('https://via.placeholder.com/600x400'),
Image.network('https://via.placeholder.com/600x400'),
Image.network('https://via.placeholder.com/400x600'),
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: Wrap(
runSpacing: 8,
children: images
.where((element) => images.indexOf(element) % 2 == 0)
.toList(),
),
),
SizedBox(width: 8),
Expanded(
child: Wrap(
runSpacing: 8,
children: images
.where((element) => images.indexOf(element) % 2 == 1)
.toList(),
),
),
],
),
),
),
),
);
}
or using list of urls:
class MyHomePage extends StatelessWidget {
final List<String> _images = [
'https://via.placeholder.com/400x600',
'https://via.placeholder.com/400x600',
'https://via.placeholder.com/600x400',
'https://via.placeholder.com/600x400',
'https://via.placeholder.com/400x600',
'https://via.placeholder.com/600x400',
'https://via.placeholder.com/600x400',
'https://via.placeholder.com/400x600',
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: Wrap(
runSpacing: 8,
children: [
for (int index = 0; index < _images.length; index += 2)
Image.network(_images[index])
],
),
),
SizedBox(width: 8),
Expanded(
child: Wrap(
runSpacing: 8,
children: [
for (int index = 1; index < _images.length; index += 2)
Image.network(_images[index])
],
),
),
],
),
),
),
),
);
}
}
If you dont want to use the staggered_grid I create the same goal with 2 Columns, left for odd index and right for even index

Expand widgets inside the Stack widget

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)),
)
],
),
),
],
),
)
],
),

What is Constraint layout's equivalent in Flutter?

Can I position a widget based on another widget?
like this:
Tiled Layout
Without
flutter_staggered_grid_view Library
There is no Widget similar to ConstraintLayout but you can achieve what you want using different widgets, like this example:
class Testing2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
child: Row(
children: <Widget>[
Flexible(
child: Column(
children: <Widget>[
Flexible(
flex: 1,
child: Container(
color: Colors.deepOrange,
),
),
Flexible(
flex: 2,
child: Container(
color: Colors.lightBlue,
),
),
],
),
),
Flexible(
child: Column(
children: <Widget>[
Flexible(
flex: 3,
child: Container(
color: Colors.orange,
)),
Flexible(
flex: 1,
child: Row(
children: <Widget>[
Flexible(
flex: 2,
child: Container(
color: Colors.blue,
)),
Flexible(child: Container(color: Colors.green))
],
),
)
],
),
)
],
),
);
}
Also you can take a look this link to know about Layout Widgets: https://flutter.io/widgets/layout/
You can try this:
https://github.com/hackware1993/Flutter-ConstraintLayout
Build flexible layouts with constraints, Similar to Android ConstraintLayout.
No matter how complex the layout is and how deep the dependencies are, each child element of ConstraintLayout will only be measured once, This results in extremely high layout performance.