Flutter: SingleChildScrollView Bottom Overflow error - flutter

I have this SingleChildScrollView Widget to make Column scrollable. However, I get the overflow error. I looked up on Flutter site to find necessary input but the example is not even showing up on my screen. How can I make this widget scrollable?
Widget build(BuildContext context) {
return SingleChildScrollView(
child: AnimatedContainer(
duration: Duration(seconds: 2),
margin: EdgeInsets.only(top: 10),
curve: Curves.fastOutSlowIn,
width: 300,
height: 500,
color: Colors.lightBlue,
child: Center(
child: Column(
children: [
aa(),
bb(),
cc(),
dd(),
],
),
),
),
);
}

It would be helpful to know constraints/sizes of these widgets aa(), bb(), cc(), dd() and also see build() method to better suggest you a solution.
But i think the issue is that you explicitly set height of AnimatedContainer to be 500 pixels, and children of these parent are taller than 500px and that's why you get overflow error. Try to not to set static heights like that. If you delete the height field i think AnimatedContainer will adjust to take such space that you won't get overflow error.

Related

How to use SingleChildScrollView without fixed width and height?

I am working the project and there is requirement to not use fixed width and height. However, I am getting pixel overflowed error. I used Expanded and other widgets but still getting an error. Code look likes this.
#override
Widget build(BuildContext context) {
return Scaffold(
child: InteractiveViewer(
minScale: 1,
maxScale: 1,
child: Center(
child: SingleChildScrollView(
child: Column(
children: [w],
),
),
),
),
);
}
In Column children we can add multiple children and page height grows with it. However, using Expanded widget is not solving the issue and getting pixel overflowed error. Using Container and MediaQuery is not required. Any solution will be appreciated. Thanks.
you can try this:
Container(height:MediaQuery.of(context).size.height,
width:MediaQuery.of(context).size.width,
child: SingleChildScrollView(
child: Column(
children: [w],
),),)

Since the Listview.builder widget in flutter requires a height, some fixed heights I give to the container wrapping the widget causes to overflow

Code
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('Search Families'),
centerTitle: true,
),
backgroundColor: StaticEntry.backColor,
body: Center(
child: FractionallySizedBox(
widthFactor: 0.8,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SearchInput(onSubmitHandler: onSubmit),
SizedBox(
height: 300,
),
resultList.isNotEmpty
? Container( // <---------------- Container that I am using to wrap the list view widget
height: 400, // <---------------- fixed height I am setting on the container that is wrapped around the ListView widget
child: ListView.builder( // <---------------- ListView widget
itemCount: 20,
itemBuilder: (context, index) {
return Text('Heyyyy!');
},
),
)
: SizedBox()
],
),
),
),
),
);
}
Problem
In the above code, as I have pointed using arrows, I am wrapping a ListView widget in a Container and assigning a fixed height to that Container since ListView widgets has an infinite height by default.
The problem with this approach is, since that height I am providing to the container is a fixed height, the layout breaks on devices with small viewport heights, while it works fine with devices that has a large viewport height.
So what I am trying to figure out is, how can I set a height to that Container that works on all devices without breaking the layout? (I am trying to make that height as maximum as possible without making the app break on smaller devices.)
(While researching about this, I came across this stack overflow link and according to that link, I tried wrapping the ListView widget with a Flexible widget and set the shrinkWrap property of the ListView widget to true. This did not work and it caused my ListView widget and the other widget to gain as much space as possible between them and pushed my ListView widget to the bottom of the screen.)

BoxConstraints forces an infinite height

child:Column(
children: <Widget>[
Container(
height: double.infinity,
width: 100.0,
color: Colors.red,
child: Text('hello'),
),)
in this,when i make height:double.infinity,it gives error in run saying **BoxConstraints forces an infinite height.**but when i give height manually it work fine.
can anyone explain me why this happening.
How about this one.
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
children: <Widget>[
Expanded(
child: Container(
// height: double.infinity,
width: 100.0,
color: Colors.red,
child: Text('hello'),
),
),
],
),
),
);
}
}
This means that you can't offer inifite height to the container. It's obvious behaviour if you don't provide the contraints to height.
You have to specify limited height to the container so that flutter can render it, if you offer it infinite it how can flutter render that and up to which constraints it would do that !
Rather you can set double.infinity to width and flutter will successfully render that because by default flutter has constraints for width it will set width to width of screen.
Considering that you have to provide height as that of screen you can use MediaQuery for that
Widget yourMethod(or build)(BuildContext context){
final screenHeight = MediaQuery.of(context).size.height;
return Column(
children:<Widget>[
Container(
height:screenHeight,//but this will be height of whole screen. You need to substract screen default paddings and height of appbar if you have one
width:100.0,
....
)
]);
}
Hope this helps !
Happy coding..
BoxConstraints forces an infinite height
Why This Happens
You're asking to render an infinite height object without a height constraint... Flutter can't do that.
Column lays out children in two phases:
Phase 1: non-Flex items (anything not Expanded, Flexible or Spacer)
done in unconstrained space
Phase 2: Flex items (Expanded,Flexible, Spacer only)
done with remaining space
Phase 1
Column's phase 1 vertical layout is done in unbounded space. That means:
no vertical constraint → no height limit
any widget with infinite height will throw the above error
you can't render an infinite height object in an infinite height constraint... that's goes on forever
Phase 2
after Phase 1 widgets have taken as much space as they intrinsically need, phase 2 Flex items share the remaining/leftover space
the remaining space is calculated from incoming constraints minus Phase 1 widgets dimensions
double.infinity height will expand to use up the remaining space
Infinite Height is OK
Here's an example of using infinite height on a Container inside a Column, which is fine:
class ColumnInfiniteChildPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
Flexible(
child: Container(
height: double.infinity, // ← perfectly fine
child: Text('Column > Container > Text')),
),
Text('Column > Text')
],
),
),
);
}
}
Remove the Flexible and the error will be thrown.

OnPressed not working inside Stack widget after Transforming a widget

In the given code,onPressed on the raised button works and translate FlatButton to the top. But onPressed on FlatButton is not working
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Transform(
transform: Matrix4.translationValues(
0.0,
_translateButton.value,
0.0,
),
child: FlatButton(
onPressed: () {
print('tapped Flat button');
},
child: Text('upper'),
),
),
RaisedButton(
onPressed: () {
animate();
print('tapped Raised button');
},
child: Text('lower'))
],
);
}
Here _translatebutton value changes from 0 to -60 when animate() is called
_animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 500))
..addListener(() {
setState(() {});
});
_translateButton = Tween<double>(
begin: 0,
end: -60,
).animate(CurvedAnimation(
parent: _animationController,
curve: Interval(
0.0,
0.75,
curve: _curve,
),
));
Wrap the Transform widget in a SizedBox (expanded or from size, depending on your requirement.
I came across this problem last week and in my case, the composition was like this:
Stack(
children: [
Widget0,
Widget1,
Opacity(
opacity: sth,
child: Transform.translate(
offset: Offset(sth),
child: Transform.rotate(
angle:sth,
child: FlatButton(
onPressed: (){sth},
child: Text("sth"),
),
),
),
),
],
)
Based on the suggestion of rahulthakur319 on the issue number
27587
I wrapped my Transform.translate composition inside a new Stack and I wrapped the stack inside a Container. Remember that the new Container should have enough width and height to show its child. I personally used MediaQuery.of(context).size.
it's working even during the complex series of animations.
The final code:
Stack(
children: [
Widget0,
Widget1,
Opacity(
opacity: sth,
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Stack(
children: [
Transform.translate(
offset: Offset(sth),
child: Transform.rotate(
angle: sth,
child: FlatButton(
onPressed: (){sth},
child: Text("sth"),
),
),
),
],
),
),
),
],
)
If your translation moves the button outside the area of the stack, the button no longer reacts to clicks. A simple way to test this is to wrap your Stack widget in a container and color it blue (or anything obvious), and if your button is moved outside the blue area, you know it's losing its clickability because it's outside of the Stack.
If this indeed is the issue, the solution is to keep the Stack inside the container, and then either set the container dimensions such that the button still stays within the border after translation, or reposition widgets relative to the container such that the translation stays within the border.
If someone is still trying to solve this issue, I solved it by wrapping the widget with IgnorePointer widget on which I don't want the pointer to reach.
reference from here
The answer I got was that in a View if an element is translated then the animation works correct but the click property is altered in someway that we can't use it after translating the element
I had this same issue my Switch widget was not working in the Stack.
The solution i found was to include it in SizeBox or Container with fixed width and height.
if your switch widget is in Row try to add Constraints on Row with SizeBox rather than adding it in every widget.

Make container widget fill parent vertically

TL;DR Need the container to fill the vertical space so that it can act as a ontap listener. Have tried most solutions but nothing seems to work.
So what I am trying to do is to make my container fill up the vertical space while still having a fixed width. Two first is what I have and third is what I want. The idea is to have the container transparent with a gesture ontap listener. If anyone have a better idea as for a different solution, feel free to suggest.
Widget build(BuildContext context) {
return new GestureDetector(
onHorizontalDragUpdate: _move,
onHorizontalDragEnd: _handleDragEnd,
child: new Stack(
children: <Widget>[
new Positioned.fill(
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new Container(
child: new IconButton(
padding: new EdgeInsets.only(top: 16.0, bottom: 16.0, left: 24.0, right: 24.0),
icon: new Icon(Icons.warning),
color: Colors.black12,
onPressed: () {},
)
),
],
),
),
new SlideTransition(
position: new Tween<Offset>(
begin: Offset(0.0, 0.0),
end: const Offset(-0.6, 0.0),
).animate(_animation),
child: new Card(
child: new Row(
children: <Widget>[
new Container(
width: 20.0,
height: 20.0,
color: Colors.amber,
),
new Expanded(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
_getListTile(),
_ifStoplineIsToBeShown()
],
),
)
],
)
),
),
],
)
);
}
I am quite sure that i have been missing something considering the fact that I have tried a lot of different things and nothing seems to work.
I have also uploaded an image with the debug painting here.
PS. I know I have set the height to a fixed value, but this is the only way to show the container.
The trick is to combine an IntrinsicHeight widget and a Row with crossAxisAlignment: CrossAxisAlignment.stretch
This force the children of Row to expand vertically, but Row will take the least amount of vertical space possible.
Card(
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
width: 20.0,
color: Colors.amber,
),
// Expanded(...)
],
),
)
)
To stretch the container to full height of the parent use property constraints:BoxConstraints.expand() in container widget. Container occupy the complete space independent of the of child widget
Container(
color: Colors.green,
child: Text("Flutter"),
constraints: BoxConstraints.expand(),
)
Please refer the link Container Cheat sheet for more about container
Simply pass in: double.infinity.
If you want a Container to fill all available space, you can just pass in:
width: double.infinity,
height: double.infinity
Explanation:
In Flutter, a child widget cannot exceed the "layout constraints" imposed by its parent widget. During the layout phase, Flutter engine uses a constraint solver to automatically correct "out-of-bound" values into what's allowed by its parent constraints.
For example, if you have a Container that's 50x50, and for its child, you pass in another Container that's 300x300, the inner container will be automatically corrected to "not exceed its parent", thus 50x50. Therefore, using sufficiently large values would always make sure you "fill parent".
In fact, even BoxConstraints.expand() exploits the same idea internally. If you open up the source code of expand(), you will see:
/// Creates box constraints that expand to fill another box constraints.
///
/// If width or height is given, the constraints will require exactly the
/// given value in the given dimension.
const BoxConstraints.expand({
double width,
double height,
}) : minWidth = width ?? double.infinity,
maxWidth = width ?? double.infinity,
minHeight = height ?? double.infinity,
maxHeight = height ?? double.infinity;
So if you are absolutely certain you want to fill all spaces, you can intuitively pass in a number bigger than the parent (or larger than the whole screen), like double.infinity.
As of Jan 2020 the simplest is to use an Expanded Widget
Expanded(flex: 1,
child: Container(..),
),
https://api.flutter.dev/flutter/widgets/Expanded-class.html
There are many answers which suggest using two things
constraints: BoxConstraints.expand(),
height: double.infinity,
But both these answer will give you an error like
BoxConstraints forces an infinite height.
We can avoid these by calculating the height of the screen like
App Bar
Top Bar Space(Exist on the above App Bar)
Remaining screen
1. Get the MediaQuery
final mediaQuery = MediaQuery.of(context);
2. Declare the AppBar Widget and same App Bar instance should be used in Scaffold App Bar
final PreferredSizeWidget appBar = AppBar(
title: Text('Home'),
);
3. Use calculated height
Container(
width: mediaQuery.size.width,
height: (mediaQuery.size.height -
appBar.preferredSize.height -
mediaQuery.padding.top),
color: Colors.red,
),
Output:
Set the height or width of a container to double.maxFinite
Container(
height: double.maxFinite,
width: 100,)
You can make your widget take the full size of a Container widget, and then set the container's height and/or width to double.maxFinite. This will make the Container take the height and/or width or its parent widget
I propose using Expanded widget (which allows us to avoid IntrinsicHeight widget), combine it with the Container's alignment property and therefore make it work properly even if the Container is not the only one at the screen.
Expanded(
child: Container(
alignment: Alignment.center,
child: Text('Your text', textAlign: TextAlign.center))),
That way one also avoids potential app's crash which occurs often when you accidentally expand to infinity some parts of the widget tree both horizontally and vertically (that is why you are not able to use BoxConstraints widget in many cases).
One can read more about the problems of passing constraints in Flutter here - a must read: https://medium.com/flutter-community/flutter-the-advanced-layout-rule-even-beginners-must-know-edc9516d1a2
This work works for me
height: MediaQuery.of(context).size.height,