i am searching a way for sizing a element in flutter with the dimensions of the parent widget. How can I do?
I tried with MediaQuery.of(WidgetParent) but this not work.
Thanks
If you want to size the current widget with respect to the parent widget's dimensions, check this Widget FractionallySizedBox
The MediaQuery.of(context) returns the device's screen size, not the parent widget.
You can get the size of the parent widget by using the LayoutBuilder.
YOUTUBE: LayoutBuilder (Flutter Widget of the Week)
LayoutBuilder(
builder: (context, constraints) {
constraints.maxWidth;
...
}
);
Related
Case1:
Consider this code:
import 'package:flutter/material.dart';
void main(List<String> args) {
runApp(const Foo());
}
class Foo extends StatelessWidget {
const Foo({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
builder: (context, child) => Scaffold(
body: Column(
children: [
ListView(), // This will cause the error
], // Vertical viewport was given unbounded height.
), // Viewports expand in the scrolling direction to fill their container. In this case, a vertical
), // viewport was given an unlimited amount of vertical space in which to expand.
);
}
}
Case2:
But When the listview is wrapped inside Expanded widget it does't give that error for example:
import 'package:flutter/material.dart';
void main(List<String> args) {
runApp(const Foo());
}
class Foo extends StatelessWidget {
const Foo({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
builder: (context, child) => Scaffold(
body: Column(
children: [
Expanded(child: ListView()), // NO issue everything is fine
],
),
),
);
}
}
Now i the question arises that as the Column give unbounded height(in case1) constrains to listview and as the listview want to be of infinite height which raiase the unbounded height error but when the listview is wrapped inside expanded it doesn't give unbounded height error that means that the expanded give the listview bounded constrains.
But how does expanded decides the constrains as the column still gives him unbounded height.
This question is realted to the answer given here :https://stackoverflow.com/a/73571651/19801146 as i can't comment there so i asked new.
I readied the Api docs of column, expanded and the understanding constrains article to understand that why this happened but not able to find the answer.
And if anyone explain me the flutter layout in detail i will be so thankful as i readied the layout article but not able to wrap me head around that.
Refering to the same Q&A you´re talking about (Flutter: If constraints go down and sizes go up, then why does Expanded exist?):
If the parent tells a child it can have a minimum of 80 pixels and a
maximum of 80 pixels, then yes, the parent is in practice telling the
child its size, as the only answer the child can give here is 80
pixels. This is called a "tight" constraint.
That's exactly what the Expanded does. It tells the child it must have
at min and at max the same size as the Expanded, so that the child can
only "decide" to have the same size of the Expanded.
So, basically, if you use only ListView or any of its variations such as ListView.builder they´ll want to expand to unbounded height (that´s why you should use shrinkwrap = true when using ListView inside of Flexible widgets), but if you use Expanded then it´ll take the parent size (height in this case) and use it to constraint the ListView´s height.
I am using a ListView Builder, and that has to be wrapped inside a Container. If i don't give a height parameter then i get Vertical viewport was given unbounded height. Now, because of this if i only have 1 item in the list, any content comes after the container, which wastes a lot of screen real estate and doesn't look aesthetically pleasing.
How can i make the parent widget i.e Container() to adjust to the size of child widget ListView.builder() ?
Add this shrinkWrap: true to your ListView and Remove Height from container.
snippet code:
return Container(
child: ListView.builder(itemBuilder: (context, index) {
return listItem(itemArray[index]),
},
itemCount: itemArray.length,
shrinkWrap: true),
);
I'm new to flutter, I have created a multistate toggle button but I want to convert it into dropdown in case the container doesn't have enough space to show the widget. Earlier I was using the LayoutBuilder context width but it is taking the whole width of the page not of the container containing the widget. Can you please help me with this ?
You are using the right approach. LayoutBuilder would work for you, but you should factor the entire widget into its own StateLess widget and use that context to do your measurements.
LayoutBuilder provides a BoxConstraints object with minWidth, maxWidth, minHeight, maxHeight properties that you can use in your code to decide which widget to embed in the tree. The dimension of that BoxConstraints object are calculated from your Widget's immediate ancestor.
Supposed you create MyMultistateToggleBoxOrDropdownWidget() and implement its build method like this:
#override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
// If constraints.maxWidth isn't wide enough,
// return a dropdown Widget,
// otherwise return the multistate toggle box.
}
}
Now that you have a Widget that returns what you want based on width, you need to now wire it into the correct context.
What you're probably missing is that you need to wrap your custom widget inside of something that controls the screen space that you want to present your Widget inside. A SizedBox() will do for this example.
Your solution took the whole page width because that was the width of your Widget's immediate ancestor in the Widget tree.
SizedBox(
width: 100.0,
height: 100.0,
child: MyMultistateToggleBoxOrDropdownWidget()
)
This is my simple outline code to generate ListView inside Future builder.
What I wanted to achieve is that I want some widget below of the FutureBuilder widget so I wrapped it with column but the content of future builder got just vanished after adding, but before adding it was fine.
Widget build(BuildContext context) {
child:FutureBuilder(
future: msDB.getListOfMoviesSeries(widget.type,widget.isWatched),
builder: (BuildContextcontext, AsyncSnapshot<List<MovieSeries>> snapshot) {
return ListView.builder(itemBuilder: (context, index) {
return ListTile(
........
)
}
);
}
);
}
Since you are using ListView in Column, The Column has an unbounded height in the vertical axis and your ListView will try to expand to maxHeight and the flutter framework will throw an error. By setting shrinkWrap to true, the extent of the scroll view in the scroll direction is determined by the contents being viewed
So to fix the issue you add following line in your ListView.builder
shrinkWrap:true
You can read more about shrinkWrap here
Hope this helps!
To get the size/position of a widget on screen, I can use GlobalKey to get its BuildContext and then find the RenderBox.
But for ErrorWidget(Red Screen) when build() error happened I want to calculate the error area's size, and then decide whether to destroy the page or replace with other widget e.g. Container().
I have already used ErrorWidget.builder create custom ErrorWidget, but need to be more precise, different sizes of ErrorWidget are treated differently. How to get ErrorWidget size for rebuild?
ErrorWidget do not evade the widgets rules.
A widget cannot depend on the size of anything else.
You can, however, use LayoutBuilder to calculate the available size.
LayoutBuilder Widget can help us know how much space is available for the child widget, before finally build it. It's builder function has parameters BuildContext context, BoxConstraints constraints.
BoxConstraints constraints provides us with the opportunity to execute custom logic.
ErrorWidget.builder = (FlutterErrorDetails details) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
Size screenSize = MediaQuery.of(context).size;
double screenRatio = (constraints.maxWidth * constraints.maxHeight) /
(screenSize.width * screenSize.height);
if (screenRatio < ACCEPTABLE_SCREEN_RATIO) {
return Container();
}
return ErrorWidget(details.exception);
},
);
};