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

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

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

Keyboard hides Textfield even if resizeToAvoidBottomInset is true

Unfortunately the Keyboard hides the TextField if it gets opened.
I also tried resizeToAvoidBottomInset: true, but it remains causing Render OverFlow error.
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: getPrimaryDarkColor(),
resizeToAvoidBottomInset: true,
body: Stack(
children: [
Positioned(
bottom: -10,
child: Image.asset(
"assets/login_path_background.png",
width: 350,
color: getPrimaryColor().withOpacity(0.4),
),
),
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
How can I fix this?
wrap the body in a SingleChildScrollView
Wrap the Column in a SizedBox with device height as it’s height and the device width as it’s width. Then, inside that SizedBox, wrap the Column with a SingleChildScrollView. I had this same exact issue and just using a SingleChildScrollView does not work because the Stack item has no specific size or position. When you wrap the whole SingleChildScrollView in a SizedBox with the device size it works. Hope this helps!

ListView Builder vs SingleChildScrollView + Row combo

I want to make a responsive UI in my app. In my home page, I have ScrollView->Column->childrens structure.
When I want to use horizontal Listview.builder in my column, it throws me error because height is unbounded. I fix it with wrapping my listview builder with container and I give this container a height value. But I dont want to give this height hardcoded,
I want to make my container height to its own child's height. I searched it and found a solution like ScrollView->Row->list.generate instead of ListView.Builder. But is it okay to make it like this? Does it cause performance problems or is it a bad practice?
My list isn't big. It has max 20 elements
For example this throwing error:
#override Widget build(BuildContext context) {
return Container(
color: Colors.red,
child: SingleChildScrollView(
child: Column(
children: [
ListView.builder(
itemCount: 5,
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return Container(
width: 200,
height: 200,
);
},
)
],
)),
); }
But this does not throw an error
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: List.generate(
5,
(index) => Container(
width: 200,
height: 200,
color: Colors.red,
)),
),
),
],
));
}
To clarify for everyone:
ListViews generate their children "lazily" - meaning they won't be drawn until they have been shown on screen. This means, of course, that they do not know the height of their items.
For example, if the ListViews children have heights similar to this list:
ooooOooo
But only this part was shown on the screen:
oooo | Oooo
And the ListView set it's height to fit "o" then it wouldn't be able to fit "O" when it eventually came on screen.
On the other hand, Rows do draw all of their children on spawn, meaning that, while they do know the size for all their widgets, they can become very slow quickly.
I would not suggest using images inside rows with 2-digit+ children, as they can be laggy not only on their initial draw, but also while the user does other things in the page containing said row - things such as scrolling up/down the page.
While testing I found that a row with just 30 children of the same stack (a small AssetImage on top of an IconImage) would lag the entire page when just scrolling up/down - not even scrolling along the row itself.
My recommended solution for you Ahmet, even though you don't want to hard-code your ListView's height, is to settle and set your ListView's height using:
MediaQuery.of(context).size.height * (percentage of screen's height you'd like for the ListView to take).

How to do a stacked widget with a scrollable widget and non scrollable widget

I want to do a screen where there is a scrollable widget and a non-scrollable widget where the non-scrollable will be on top of the scrollable widget in dart flutter.
I have tried something this: pseudo-code:
Stacked(
children: <Widget>[
SingleChildScrollView(
child: // scrollable widget
),
Align(
alignment: Alignment.bottomCenter,
child: // non-scrollable widget eg container
),
]
)
But the scrollable widget is not scrolling. No error with this implementation but scrolling not working
The problem here is that the non scrollable widget is on top of the scrollable one and tends to block all the touch event to the bottom widget (the scrollable one.)
you have several ways to fix this, the first one is to wrap your non scrollable widget inside an IgnorePointer
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(children: [
ListView.builder(itemBuilder: (context, index) {
return Text("item ${index + 1}");
}),
IgnorePointer(
child: Align(
alignment: Alignment.bottomCenter,
child: Container(color: Colors.red.withAlpha(50))),
),
]));
}
but this will prevent any input on the overlapping widget
If you want to achieve the same, but being able to interact with the overlapping widget, you may want to change the IgnorePointer with a GestureDetector, and play with the behaviors https://api.flutter.dev/flutter/widgets/GestureDetector/GestureDetector.html

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.