I want to divide my row in flutter into 4 columns with the same width. So far, the solution I came up with is this,
child: Row(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width * 0.25,
decoration: BoxDecoration(color: Colors.greenAccent),
),
Container(
width: MediaQuery.of(context).size.width * 0.25,
decoration: BoxDecoration(color: Colors.yellow),
),
Container(
width: MediaQuery.of(context).size.width * 0.25,
decoration: BoxDecoration(color: Colors.blue),
),
Container(
width: MediaQuery.of(context).size.width * 0.25,
decoration: BoxDecoration(color: Colors.white),
),
],
),
Is there any alternative to this. Also dividing the row into 1/3 ratio would not work in this method.
You can achieve this by using an Expanded Widget
Check the code below:
It works perfectly well.
1) For 1/3 ratio
Row(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
width: MediaQuery.of(context).size.width * 0.25,
decoration: BoxDecoration(color: Colors.greenAccent),
),
),
Expanded(
flex: 1,
child: Container(
width: MediaQuery.of(context).size.width * 0.25,
decoration: BoxDecoration(color: Colors.yellow),
),
),
Expanded(
flex: 1,
child: Container(
width: MediaQuery.of(context).size.width * 0.25,
decoration: BoxDecoration(color: Colors.blue),
),
),
],
),
1) For 1/4 ratio
Row(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
width: MediaQuery.of(context).size.width * 0.25,
decoration: BoxDecoration(color: Colors.greenAccent),
),
),
Expanded(
flex: 1,
child: Container(
width: MediaQuery.of(context).size.width * 0.25,
decoration: BoxDecoration(color: Colors.yellow),
),
),
Expanded(
flex: 1,
child: Container(
width: MediaQuery.of(context).size.width * 0.25,
decoration: BoxDecoration(color: Colors.blue),
),
),
Expanded(
flex: 1,
child: Container(
width: MediaQuery.of(context).size.width * 0.25,
decoration: BoxDecoration(color: Colors.white),
),
),
],
),
See output below:
I hope this answers your questions.
You can use Expanded or Flexible, by default it has flex: 1, and you can change the values depending on your need.
Row(
children: [
Expanded(
flex: 1, // you can play with this value, by default it is 1
child: Child1(),
),
Expanded(
flex: 1,
child: Child2(),
),
Expanded(
flex: 1,
child: Child3(),
),
Expanded(
flex: 1,
child: Child4(),
),
],
);
As it's not mentioned in the above solutions. Flex is the proportion to be occupied in the available widget. If you're using 2 Expanded widgets one with flex 1 and the other with flex 3 then available space will be occupied as 1/4 by the first Expanded widget and 3/4 by the other.
Related
Is there any way to set the max size of the Expanded or Flex widget in Flutter?
Containers constraints are not working at all.
Row(
children: [
Container(
decoration: BoxDecoration(
color: Colors.red,
),
child: SizedBox(
height: 30,
width: 50,
),
),
Flexible(
child: Container(
constraints:
const BoxConstraints(minWidth: 50, maxWidth: 100),
decoration: BoxDecoration(
color: Colors.blue,
),
child: SizedBox(
height: 30,
),
),
),
Container(
decoration: BoxDecoration(
color: Colors.green,
),
child: SizedBox(
height: 30,
width: 50,
),
),
],
),
What I want: Max Width
I tryed Everythig. Really.
Limit max width of Container in Flutter
This didn't help me.
The Expanded widget is supposed to take all the space available in a Row or a Column so you can't just limit its size by using SizedBox or any other method but you can do either of two things whichever suits your needs to limit its size:
Using the flex property of the Expanded Widget:
Row(
children: [
Expanded( //wrap all the widgets in your row with expanded
flex:1, //and provide a flex property (higher number equals more space taken)
child: Container(
decoration: BoxDecoration(
color: Colors.red,
),
child: SizedBox(
height: 30,
width: 50,
),
),
),
Expanded(
flex:2, // which means flex:2 will take twice the amount
child: Container(
constraints:
const BoxConstraints(minWidth: 50, maxWidth: 100),
decoration: BoxDecoration(
color: Colors.blue,
),
child: SizedBox(
height: 30,
),
),
),
Expanded(
flex:1, //same for this one
child: Container(
decoration: BoxDecoration(
color: Colors.green,
),
child: SizedBox(
height: 30,
width: 50,
),
),
),
],
),
Result:
Limiting the width of the Row itself:
SizedBox( //wrap your Row with a SizedBox and give it some width
width: 200,
child: Row(
children: [
Container(
Result:
Edit: As you want to have an adaptable container you just need to change some things:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, //add mainAxisAlignment to give spaceBetween the containers
children: [
Container(
decoration: BoxDecoration(
color: Colors.red,
),
child: SizedBox(
height: 30,
width: 50,
),
),
Container(
height: 30, //give you container some height instead of a child SizedBox
constraints:
BoxConstraints(minWidth: MediaQuery.of(context).size.width/10, maxWidth: MediaQuery.of(context).size.width/5), // add responsive constraints which change values according to your screen size
decoration: BoxDecoration(
color: Colors.blue,
),
child: Expanded(child: Container(),) //give it an Expanded widget to take in all the maxWidth
),
Container(
decoration: BoxDecoration(
color: Colors.green,
),
child: SizedBox(
height: 30,
width: 50,
),
),
],
),
And then you'll get this:
Shrinked:
Unshrinked:
I have the following code:
return Scaffold(
body: SafeArea(
child: ListView(children: [
Container(
child: Center(
child: Row(children: [
Flexible(
child: Container(
margin: const EdgeInsets.fromLTRB(10, 15, 5, 15),
decoration: BoxDecoration(color: Colors.white),
child: Row(children: [
Container(
height: 20,
width: 20,
decoration: BoxDecoration(color: Colors.black38),
),
Expanded( // <- does nothing. container still 0x0px
child: Container(
decoration: BoxDecoration(color: Colors.black38),
)),
]),
))
])))
]),
));
I am trying to expand the third container to the remaining size of the Row it's in, but somehow it always stays 0x0 pixel in size, until I define a manual size by using height: or/and width:.
Thanks for any help!
I could be wrong, but I think it's actually not 0 x 0 but [remaining width] x 0. You will see that just putting a height will make it visible. Also when putting a 3rd widget in the row you will see it will be pushed all the way to the right.
The thing is that, as far as I understand it, a Row expects it's children to provide a height. Because otherwise it doesn't know how high it needs to be. What height do you expect the Expanded to be? 20 like the other container? full height of the screen? If a widget inside a Row doesn't provide a height it will be made as small as possible, so in this case, invisible.
What probably helps is to wrap the row in an IntrinsicHeight like this:
return Scaffold(
body: SafeArea(
child: ListView(children: [
Container(
child: Center(
child: Row(children: [
Flexible(
child: Container(
margin: const EdgeInsets.fromLTRB(10, 15, 5, 15),
decoration: BoxDecoration(color: Colors.white),
child: IntrinsicHeight(child: Row(children: [
Container(
height: 20,
width: 20,
decoration: BoxDecoration(color: Colors.black38),
),
Expanded( // <- does nothing. container still 0x0px
child: Container(
decoration: BoxDecoration(color: Colors.black38),
)),
]),
)))
])))
]),
));
try this
Container(
child: Center(
child: Row(children: [
Flexible(
child: Container(
margin: const EdgeInsets.fromLTRB(10, 15, 5, 15),
decoration: BoxDecoration(color: Colors.white),
child: Row(children: [
Container(
height: 20,
width: 20,
decoration: BoxDecoration(color: Colors.black38),
),
Expanded(
child: Container(
height: 20,
decoration: BoxDecoration(color: Colors.pink),
),
),
]),
))
]))),
I'm trying to design the following layout using flutter for a website, but I can't figure out the right pattern for doing so.
I tried many possibilities with columns and rows; I tried also using a stack, but whatever I use, either 3-4 won't become scrollable, or 5 won't take the height that it's given. Is there a workaround for this layout to be implemented?
You can easily accomplish what you want using this library.
flutter_staggered_grid_view
If you want your layout to take up entire screen, key is to use percentages of screen height for mainAxisExtent of StaggeredGridTile.extent
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(
MaterialApp(
home: AppView(),
),
);
}
class AppView extends StatelessWidget {
const AppView({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
var list = List<int>.generate(100, (i) => i);
var height = MediaQuery.of(context).size.height;
return Scaffold(
body: StaggeredGrid.count(
crossAxisCount: 3,
axisDirection: AxisDirection.down,
mainAxisSpacing: height * 0.015,
crossAxisSpacing: height * 0.015,
children: [
StaggeredGridTile.extent(
crossAxisCellCount: 1,
mainAxisExtent: height * 0.08,
child: Container(
color: Colors.amber,
),
),
StaggeredGridTile.extent(
crossAxisCellCount: 1,
mainAxisExtent: height * 0.08,
child: Container(
color: Colors.amber,
),
),
StaggeredGridTile.extent(
crossAxisCellCount: 1,
mainAxisExtent: height * 0.08,
child: Container(
color: Colors.amber,
),
),
StaggeredGridTile.extent(
crossAxisCellCount: 2,
mainAxisExtent: height * 0.08,
child: Container(
color: Colors.red,
),
),
StaggeredGridTile.extent(
crossAxisCellCount: 1,
mainAxisExtent: height * 0.675,
child: Container(
color: Colors.blue,
),
),
StaggeredGridTile.extent(
crossAxisCellCount: 1,
mainAxisExtent: height * 0.81,
// mainAxisCellCount: 1.2,
child: Container(
color: Colors.pink,
child: ListView(
children: list.map((e) => Text(e.toString())).toList(),
),
),
),
StaggeredGridTile.extent(
crossAxisCellCount: 1,
mainAxisExtent: height * .58,
child: Container(
color: Colors.orange,
child: ListView(
children: list.map((e) => Text(e.toString())).toList(),
),
),
),
StaggeredGridTile.extent(
crossAxisCellCount: 2,
mainAxisExtent: height * .23,
child: Container(
color: Colors.teal,
),
),
],
),
);
}
}
Use this
Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
height: (MediaQuery.of(context).size.height) / 2,
child: Stack(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 2,
child: Column(
children: [
Container(
margin: EdgeInsets.all(4),
width: double.infinity,
height: (MediaQuery.of(context).size.height) / 8,
child: SizedBox(
height: 1,
width: 1,
child: const ColoredBox(color: Colors.amber),
)),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 2,
child: Container(
margin: EdgeInsets.all(4),
height:
(MediaQuery.of(context).size.height) / 3,
child: SizedBox(
height: 1,
width: 1,
child:
const ColoredBox(color: Colors.amber),
)),
),
Expanded(
flex: 1,
child: Container(
margin: EdgeInsets.all(4),
height: (MediaQuery.of(context).size.height) /
7.5,
child: SizedBox(
height: 1,
width: 1,
child:
const ColoredBox(color: Colors.amber),
)),
),
],
),
],
),
),
Expanded(
flex: 1,
child: Container(
margin: EdgeInsets.all(4),
height: ((MediaQuery.of(context).size.height) / 4) + 12,
child: SizedBox(
height: 1,
width: 1,
child: const ColoredBox(color: Colors.amber),
)),
),
],
),
Align(
alignment: Alignment.bottomRight,
child: Container(
padding: EdgeInsets.only(bottom: 20),
margin: EdgeInsets.all(4),
width: (MediaQuery.of(context).size.height) / 3.8,
height: (MediaQuery.of(context).size.height) / 5,
child: SizedBox(
height: 1,
width: 1,
child: const ColoredBox(color: Colors.amber),
)),
)
],
),
),
),
There is a github project for design a responsive screen.
The github link Flutter-Responsive-Admin-Panel-or-Dashboard
Probably not the best question title but I would like to get some feedback on whether or not my layout could/should be simplified.
I want to get the following layout in Flutter (see image)
in a Container (light green)
I want a a centered central row (dark green) containing 80% of the width and 20% of the height
the row contains three spaced elements (red, blue and orange)
the red one contains a red centered 80% Container
The following code works but feels pretty complicated. Are there more elegant ways to achieve the same thing?
Container(
color: Colors.white,
child: Column(children: [
Expanded(
child: SizedBox.expand(
child: FractionallySizedBox(
widthFactor: 0.8,
heightFactor: 0.2,
alignment: FractionalOffset.center,
child: Container(
child: Row(
children: [
Flexible(
flex:2,
child: SizedBox.expand(child: Container(
color: Colors.red,
child: FractionallySizedBox(
widthFactor: 0.8,
heightFactor: 0.8,
child: Container(color:Colors.yellow),
)
)
),
),
Spacer(),
Flexible(flex:2, child: Container(color: Colors.blue)),
Spacer(),
Flexible(flex:2, child: Container(color: Colors.orange)),
],
))),
),
)
])),
It is not much change but it is something simpler:
Size size = MediaQuery.of(context).size;
return Container(
color: Colors.white,
child: Center(
child: Container(
height: size.height * 0.2,
width: size.width * 0.8,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
width: size.width * 0.2,
color: Colors.red,
child: FractionallySizedBox(
widthFactor: 0.8,
heightFactor: 0.8,
child: Container(color: Colors.yellow),
)),
Container( width: size.width * 0.2, color: Colors.blue),
Container( width: size.width * 0.2, color: Colors.orange),
],
),
),
));
I have tried to achieve the effect shown in the highlighted portion of the image with the following code, but this produces counter-intuitive and wrong results.
Just to avoid confusion, I am talking about the effect of the middle of the smaller containers being aligned with the bottom of the large orange-ish container
My code is as follows:
Size size = MediaQuery.of(context).size;
double height = size.height;
double width = size.width;
return Column(
children: [
Expanded(
flex: 3,
child: Container(color: Colors.white),
),
Positioned(
top: height * (3 / 5) - height * 0.15 / 2,
child: Container(
color: Colors.green,
height: height * 0.15,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: height * 0.15,
width: width * 0.45,
color: Colors.red,
),
Container(
height: height * 0.15,
width: width * 0.45,
color: Colors.blue,
)
],
),
),
),
Expanded(
flex: 5,
child: Container(color: Colors.black),
),
],
);
How can I improve upon my code?
You will need to use the Stack widget to achieve this result.
Stack(children: [
Container(
height: 230,
decoration: BoxDecoration(
color: Colors.orange,
)),
Column(children: [
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
height: 100,
width: 100,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(22))),
Container(
height: 100,
width: 100,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(22))),
Container(
height: 100,
width: 100,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(22))),
]),
),
])
])