How to make the width of a container match its height - flutter

I have a Container which has a height based on its parent which is an Expanded with a flex of 2. I need the height and the width to be the same. I don't want to create a fixed width such as width: 100.0. Is it possible to make the width match the height of this Container inside an Expanded?

For that you'll have to use LayoutBuilder, here is the minimal code:
Column(
children: <Widget>[
Expanded(
flex: 2,
child: LayoutBuilder(
builder: (_, constraints) {
return Container(
color: Colors.blue,
width: constraints.maxHeight, // width is made equal to height
);
},
),
),
Expanded(
flex: 9,
child: Container(color: Colors.orange),
),
],
)
Edit: As #pskink and other mentioned you can also use AspectRatio
AspectRatio(
aspectRatio: 1,
child: Container(color: Colors.blue),
)

Aspect Ratio will work
AspectRatio(
aspectRatio: 1,
child: Container(
color: Colors.red,
),
)

Related

How to layout these widgets in Flutter?

I'm developing a desktop app using Flutter, which have three widgets as above, a scrollable widget, an expended widget with a min-width, and a fixed-width widget. Notice that, the first widget is a horizontal scroll widget, so its width depends on its contents.
I know the whole width, but to set the max-width of the scrollabe widget, I need to know the min-size of the Expanded widget and the width of the fixed-width widget.
As a newbie of Flutter, I really have no idea how to layout these widgets.
Andbody help!
Few ways of providing space like providing flex on Flexiable/Expnaded widget, using LayoutBuilder/MediaQuery or just provide Expanded one of it to get available space.
You can test this widget
return Scaffold(
body: LayoutBuilder(
// in case of needed
builder: (context, constraints) {
return Row(
children: [
SizedBox(
width: constraints.maxWidth * .6,
child: ListView.builder(
itemBuilder: (context, index) => ListTile(
tileColor: index.isEven ? Colors.red : Colors.deepPurple,
),
)),
//or just use Expanded for available width
Expanded(
child: Container(
// width:constraints.maxWidth * .4-100,
// constraints: BoxConstraints(
// minWidth: 200,
// // constraints.maxWidth * .6 - 100,
// maxWidth: constraints.maxWidth * .4 - 100,
// ),
color: Colors.cyanAccent,
child: Column(
children: [
Text("an Expamed with min 2idth"),
],
),
),
),
Container(
width: 100,
height: 200,
color: Colors.red,
child: Text("Fixed-width widget"),
)
],
);
},
),
);
You can use a row and use containers with constrains to achieve this layout. For example.
Row(
children:[
Container(
constrains: BoxConstrain(
maxWidth: MediaQuery.of(context).size.width*0.5
),
child: SingleChildScrollView ()
),
Expanded(
child : Container(
constrain : BoxConstrain (
minWidth : MediaQuery.of(context).size.width*0.2
)
)
),
SizedBox(
width: MediaQuery.of(context).size.width*0.3,
)
]
)

I tried to wrap column with Singlechildscrollview Flutter but screen goes blank

[enter image description here][1]
Inside My column, there is a stack, a carousel slider,a gridview builder. I want to scroll all of them together. I tried to use singlechildscrollview as you can see in the code below. Please Someone help me how can I scroll those things together.
[1]: https://i.stack.imgur.com/FYexC.png` enter code here`
Scaffold(
backgroundColor: Colors.orange,
// Color(0xFFFFF176),
body: SingleChildScrollView(
child: Column(
children: [
Expanded(
child: Stack(
alignment: Alignment.bottomCenter,
children: [
CarouselSlider(
items: slideImage
.map((image) =>
Builder(builder: (BuildContext context) {
return Container(
height: 200,
width: 500,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40),
image: DecorationImage(
image: AssetImage(image),
fit: BoxFit.fill),
),
);
}))
.toList(),
options: CarouselOptions(
onPageChanged: (index, reason) {
setState(() {
activeIndex = index;
});
},
height: 300,
viewportFraction: 1,
autoPlay: true,
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: AnimatedSmoothIndicator(
activeIndex: activeIndex, count: slideImage.length),
),
],
),
),
SizedBox(
height: 10,
),
Expanded(
child: GridView.builder(
shrinkWrap: true,
// physics: NeverScrollableScrollPhysics(),
itemCount: menuImage.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 0.8,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
),
itemBuilder: (context, index) => Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
color: Color(0xFFFFFDE7),
elevation: 10,
child: GridTile(
child: Column(
children: [
Image.asset(
menuImage[index],
fit: BoxFit.fill,
),
Text(
title[index],
style: TextStyle(fontSize: 18),
),
],
),
),
),
),
),
],
),
),
);
}
}
It would be best if you gave height to the column you are using singlechildeScrollview.
Wrap column widget in container or sizedbox widget and give it height.
column widget has children widget GridView.builder that is wrapped in expanded so gridview.builder will try to take all available height in the column which will be infinite because it's not defined and you will get column covering screen taking infinite screen height in short blank screen.
In flutter, Column will take height as much as it can, SingleChildScrollView child dont have height (infinite). Combine together, Flutter don't know how to render them correctly and causing error.
To solve it, try to determine the height of Column by widgget like SizedBox or determine the mainSize.min.
Another way to solve it is wrap Column by IntrinsicHeight but not recommend cause it heavy.
If it takes too much height. so give height to the column.
like this..
SingleChildScrollView(
child: SizedBox(
height: 500,
child: Column(
children: const [...],
),
),
)
your expanded widget is taking whole space of column try removing it or replacing it with Sizedbox.

Flutter card layout with column

I have a simple card design, my card is wrapped with a container with a specific height and width, so the children are bounded
The card has a picture from Image.network and a text at the bottom, both occupying half the height of the card
However, my code receives this error:
Error: Cannot hit test a render box that has never been laid out.
From what I know, constraints goes down the tree and children return the size to the parent. I know the column would not pass constraints to the children, however, the two expanded widget SHOULD know to take up half of the card's height?
My goal is to understand WHY this doesn't work, moreover than the actual working code. thank you!
Code:
var height = MediaQuery.of(context).size.height;
return Container(
height: height * 0.45,
width: double.infinity,
child: Card(
elevation: 4,
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
child: Column(
children: [
Expanded(
flex: 1,
child: FittedBox(
child: Image.network('https://source.unsplash.com/random'),
),
),
Expanded(
flex: 1,
child: Container(
child: Text("hello"),
),
)
],
)),
);
The problem is that FittedBox tries to scale its child to fit accordingly; thus the child needs to be laid out before. Because the child is an image being loaded in this example, it's not laid before the fitting. To overcome this issue, you can use a SizedBox.expand instead of the FittedBox:
Container(
height: height * 0.45,
width: double.infinity,
child: Card(
elevation: 4,
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
child: Column(
children: [
Expanded(
flex: 1,
child: SizedBox.expand(
child: Image.network('https://source.unsplash.com/random'),
),
),
Expanded(
flex: 1,
child: Container(
child: Text("hello"),
),
)
],
)),
)
-Don't use MediaQuery inside the build Methode, before the return.
-Avoid redundant argument: https://dart-lang.github.io/linter/lints/avoid_redundant_argument_values.html for the flex: 1
Use fit: BoxFit.contain
return Container(
height: MediaQuery.of(context).size.height* 0.45,
width: double.infinity,
child: Card(
elevation: 4,
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
child: Column(
children: [
Expanded(
flex: 1,
child: Image.network('https://source.unsplash.com/random',fit: BoxFit.contain),
),
Expanded(
flex: 1,
child: Container(
child: Text("hello"),
),
)
],
)),
);

Grow a container while maintaining heights of the other containers in flutter

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

Why does AspectRatio not work in a ListView?

Why does AspectRatio not preserve my aspect ratio when it is placed in a ListView?
Unexpected behaviour (doesn't preserve aspect ratio in a ListView)
return ListView(
children: [
Container(
height: 200,
child: AspectRatio(
aspectRatio: 1 / 2,
child: Container(
color: Colors.red,
),
),
),
],
);
Expected behaviour (works outside of a ListView)
return Container(
height: 200,
child: AspectRatio(
aspectRatio: 1 / 2,
child: Container(
color: Colors.red,
),
),
);
This is because "in the cross axis, the children are required to fill the ListView." So the ListView stretches the Container.
The solution will be to wrap the Container in a Center widget which helps maintain the child widget size "in case the parent widget has its own opinions regarding the size that the Container should take" like below:
Center(
child: Container(
height: 200,
child: AspectRatio(
aspectRatio: 1 / 2,
child: Container(
color: Colors.red,
),
),
),
)