Flutter - How to get Container with children to take up entire screen - dart

As per Flutter docs Containers with no children try to be as big as possible unless the incoming constraints are unbounded, in which case they try to be as small as possible. Containers with children size themselves to their children. The closest I've been to getting it to work:
return Stack(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
//width: Device.screenWidth,
//height: Device.screenHeight,
child: Column(
children: <Widget>[(view[1])],
),
),
Container(
width: MediaQuery.of(context).size.width * .50,
height: MediaQuery.of(context).size.width * .50,
child: Column(
children: <Widget>[(view[0])],
),
),
],
);
I/flutter (12292): The following message was thrown during layout:
I/flutter (12292): A RenderFlex overflowed by 81 pixels on the bottom.
I/flutter (12292): The overflowing RenderFlex has an orientation of Axis.vertical.
I/flutter (12292): The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
I/flutter (12292): black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
Can't understand why MediaQuery or Device isn't preventing overflow? The first Container always overflows by 81 pixels on both an Android phone or tablet; no iPhone or iPad to test now. Based on what I've read from other posts overflow with yellow & black is corrected simply by wrapping in a SingleChildScrollView but when I attempt to do so I get
child: SingleChildScrollView(
child: Column(
children: <Widget>[(view[1])],
),
),
I/flutter (12292): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (12292): The following assertion was thrown during performLayout():
I/flutter (12292): RenderFlex children have non-zero flex but incoming height constraints are unbounded.
I/flutter (12292): When a column is in a parent that does not provide a finite height constraint, for example if it is
I/flutter (12292): in a vertical scrollable, it will try to shrink-wrap its children along the vertical axis. Setting a
I/flutter (12292): flex on a child (e.g. using Expanded) indicates that the child is to expand to fill the remaining
I/flutter (12292): space in the vertical direction.
I/flutter (12292): These two directives are mutually exclusive. If a parent is to shrink-wrap its child, the child
.
.
.
I/flutter (12292): crossAxisAlignment: center
I/flutter (12292): verticalDirection: down
I/flutter (12292): This RenderObject had the following child:
I/flutter (12292): RenderAndroidView#e356e NEEDS-LAYOUT NEEDS-PAINT
Made several other attempts with Expanded, ClipRect & other widgets based on the errors I've seen but it just made it worse where there was no image at all. Am I missing something simple or should I attempt to fix this another way?
EDIT: As per Amsakanna the latest attempt is below but still overflows by 81 pixels to produce identical error message above in the first code block.
return Stack(
children: <Widget>[
SingleChildScrollView(
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(
children: <Widget>[view[1])],
),
),
),
I/flutter ( 1144): The following message was thrown during layout:
I/flutter ( 1144): A RenderFlex overflowed by 81 pixels on the bottom.
I/flutter ( 1144): The overflowing RenderFlex has an orientation of Axis.vertical.
I/flutter ( 1144): The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
I/flutter ( 1144): black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
Tried to use IntrinsicHeight inside SingleChildScrollView as found here in the Expanding content to fit the viewport section but it overflows too (by 81 pixels) with similar error message.

SizedBox.expand did it for me. Here is an example of displaying an image so that the image height matches the parent and the container draws a black background in the unused space:
SizedBox.expand(
child: Container(
color: Colors.black,
child: Image (
fit: BoxFit.fitHeight,
image: AssetImage('assets/myimage.png'),
),
),
);

My approach...
return Scaffold(
appBar: AppBar(
title: Text('Title'),
),
body: Container(
color: Colors.indigo[200],
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: Image.file(_image),
),
],
),
),
);

It works for me..
return Scaffold(
appBar: AppBar(
title: Text("chatEasy"),
backgroundColor: Color.fromRGBO(102, 108, 218, 1),
),
body: Container(
child: Column(
children: <Widget>[
Expanded(
child: Container(
child: Image(
image: AssetImage("images/baseScreen.png"),
fit: BoxFit.fitHeight,
),
),
),
],
),
),
);
}
}

Wrap the Container with a SingleChildScrollView() and give the container the height and width using MediaQuery. I could achieve the results using this way. This way, the screen doesn't overflow by any pixels.
return Scaffold(
body: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: , //child
),
),
);

You did it right by wrapping it inside a SingleChildScrollView.
The second error happens whenever you have a flex widget like 'Expanded' is placed inside a Column. If you did not place any expanded widget inside the first Column, probably it is the Camera widget doing that.
Try giving a definite size to your Camera widget by wrapping it inside a Container or SizedBox.

if you want to make a container height as much as its child take you may use this approach.
Card(
child: Flexible(
child: Container(
child: Column(
children: [
Container(
height: 30,
width: double.infinity,
color: Theme.of(context).primaryColor,
child: Align(
alignment: Alignment.centerLeft,
child: Container(
margin: EdgeInsets.only(left: 5),
child: Text('Presupuesto Por Profesional',style:
TextStyle(color: Colors.white, fontSize: 16,fontWeight:
FontWeight.bold)),
)
)
),
ProfessionalTableView(reportData.presupuestos)
],
),
),
)
),
My ProfessionalTableView is a dataTable and its length depends upon the size of the list I pass it. So the card size also depends upon the item I have in list.I wrap the parent Container with Flexible and it work.

wrap the Container with SizedBox.expand and add colors in SizedBox.

Related

How to handle dynamic images within a FittedBox

I am currently implementing a dropdown button as the title of a scaffold.
In this dropdown, some of the options do not have a relevant image and therefore just text is shown. I have it working great, my only problem is, an error is always thrown when the app runs (not hot reloaded) because the Image doesn't load instantaneously meaning that FittedBox is trying to fit an empty widget, once it loads it is fine, and then hot reloads work fine with no errors too because the image is already loaded. Here is my code for my DropDownMenuItems:
return DropdownMenuItem(
value: company.id.toString(),
child: Center(
child: FittedBox(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.all(10),
child: (config.companyLogos[company.id] != null)
? FittedBox(
child: Image.asset(
config.companyLogosPath +
config.companyLogos[company.id],
height: 50,
),
fit: BoxFit.contain,
)
: FittedBox(
child: Text(
company.name,
style: TextStyle(fontSize: 30),
)),
),
],
)))));
And here is the error that is thrown when the app runs, I am sure this is due to what I described above:
flutter: ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
flutter: The following assertion was thrown during performLayout():
flutter: 'package:flutter/src/rendering/box.dart': Failed assertion: line 313 pos 12: 'width > 0.0': is not
flutter: true.
Considered solutions:
A possible solution would be to supply the width of image, I could include this in my companyLogos map by making it a Map of Maps and including the filename and the width in the sub map.
However, I've trie this and it doesn't seem to work, it just makes my images a lot smaller than if I used an unset width.
I am not explicitly defining width to make it keep its aspect ratio whilst still fitting in the row.
I'm probably missing a trick here on how to handle images in flutter/dart, any help would be much appreciated, thank you!
Thanks to #pskink I have solved the issue.
I solved it by scrapping the FittedBox completely and using Image's 'fit:' property.
Here is my fixed code:
return DropdownMenuItem(
value: company.id.toString(),
child: Center(
child: FittedBox(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.all(10),
child: (config.companyLogos[company.id] != null)
? Container(
child: Image.asset(
config.companyLogosPath +
config.companyLogos[company.id],
height: 50,
fit: BoxFit.contain,
))
: FittedBox(
child: Text(
company.name,
style: TextStyle(fontSize: 30),
)),
),
],
)))));

Flutter Stepper horizontal type not working

I have a problem with changing the Stepper type from vertical to horizontal.
This is my code:
body: new ListView.builder(
itemCount: data == null ? 0 : 5,
itemBuilder: (BuildContext context, int index) {
return new Card(
//child: new Text(data[index]["title"]),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Stepper(
steps: my_steps,
type: StepperType.horizontal,
controlsBuilder: (BuildContext context,
{VoidCallback onStepContinue, VoidCallback onStepCancel}) {
return Row(
children: <Widget>[
Container(
child: null,
),
Container(
child: null,
),
],
);
},
//type: StepperType.horizontal,
),
));
},
),
After I uncomment the type I get this error:
I/flutter (10148): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY
╞═════════════════════════════════════════════════════════ I/flutter
(10148): The following assertion was thrown during performLayout():
I/flutter (10148): RenderFlex children have non-zero flex but incoming
height constraints are unbounded. I/flutter (10148): When a column is
in a parent that does not provide a finite height constraint, for
example if it is I/flutter (10148): in a vertical scrollable, it will
try to shrink-wrap its children along the vertical axis. Setting a
I/flutter (10148): flex on a child (e.g. using Expanded) indicates
that the child is to expand to fill the remaining I/flutter (10148):
space in the vertical direction.
Your ListView has unbounded heigh so it doesn't know how much space to use for each child, which is a Stepper.
Give it some constraints, such minimum height size for each and you should be fine.
(...)
ConstrainedBox(
constraints: BoxConstraints.tightFor(height: 200.0),
child: Stepper(
steps: my_steps(),
type: StepperType.horizontal,
(...)
You can use the SizedBox() or Container() widget and set it height
SizedBox(
height: 200,
child: Card(
//child: new Text(data[index]["title"]),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Stepper(
steps: my_steps(),
type: StepperType.horizontal,
controlsBuilder: (BuildContext context,
{VoidCallback onStepContinue, VoidCallback onStepCancel}) {
return Row(
children: <Widget>[
Container(
child: null,
),
Container(
child: null,
),
],
);
},
//type: StepperType.horizontal,
),
)),
)

Shorten my Text and show The orginal version in a small pop-up (TextOverflow.ellipsis gives error)

I want to shorten my Text if it is not fit the area.
for example :
the orginal text is Downtown Manhattan Tour
shorten text should be : Downtown...
and when user clicks the text,
I want to show the full text in a small pop-up which will disapear after 1 second or click somewhere else.
this is my related code:
Container(
decoration: BoxDecoration(border: Border.all(color: Colors.black26)),
height: MediaQuery.of(context).size.height / 12,
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
// we can show related user profile picture in this area, whe we click it we go to the related user page.
padding: const EdgeInsets.symmetric(horizontal: 5.0, vertical: 3.0),
child: Row(
children: <Widget>[
CircleAvatar(
backgroundImage: NetworkImage(userAction.owner.picture),
),
SizedBox(
width: 5,
),
Text(userAction.owner.firstName +
' ' +
userAction.owner.lastName)
],
),
),
Text(userAction.actionExplanation),
Padding(
// we can show tour photo here when user clicks this area user will go to the related tour page.
padding: const EdgeInsets.symmetric(horizontal: 5.0, vertical: 3.0),
child: Row(
children: <Widget>[
Expanded(
child: Text(
userAction.route.name + 'Text Longg',
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold),
),
),
SizedBox(
width: 5,
),
CircleAvatar(
backgroundColor: Colors.black26,
),
],
),
),
],
),
);
I find this answer for shorten text but it gives error in my case : Insert overflow ellipsis in text
Error Log:
I/flutter (10591): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (10591): The following message was thrown during layout:
I/flutter (10591): A RenderFlex overflowed by 73 pixels on the right.
I/flutter (10591):
I/flutter (10591): The overflowing RenderFlex has an orientation of Axis.horizontal.
I/flutter (10591): The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
I/flutter (10591): black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
I/flutter (10591): Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
I/flutter (10591): RenderFlex to fit within the available space instead of being sized to their natural size.
I/flutter (10591): This is considered an error condition because it indicates that there is content that cannot be
I/flutter (10591): seen. If the content is legitimately bigger than the available space, consider clipping it with a
I/flutter (10591): ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex,
I/flutter (10591): like a ListView.
I/flutter (10591): The specific RenderFlex in question is:
I/flutter (10591): RenderFlex#f2700 OVERFLOWING
I/flutter (10591): creator: Row ← Padding ← DecoratedBox ← ConstrainedBox ← Container ← Column ← _SingleChildViewport
I/flutter (10591): ← _ScrollableScope ← IgnorePointer-[GlobalKey#4a6a1] ← Semantics ← Listener ← _GestureSemantics ←
I/flutter (10591): ⋯
I/flutter (10591): parentData: offset=Offset(1.0, 1.0) (can use size)
I/flutter (10591): constraints: BoxConstraints(w=409.4, h=55.0)
I/flutter (10591): size: Size(409.4, 55.0)
I/flutter (10591): direction: horizontal
I/flutter (10591): mainAxisAlignment: spaceBetween
I/flutter (10591): mainAxisSize: max
I/flutter (10591): crossAxisAlignment: center
I/flutter (10591): textDirection: ltr
I/flutter (10591): verticalDirection: down
I/flutter (10591): ◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤
I/flutter (10591): ════════════════════════════════════════════════════════════════════════════════════════════════════
This is the working solution. I modified it a little bit to make it working. Try this out.
Container(
decoration: BoxDecoration(border: Border.all(color: Colors.black26)),
height: MediaQuery.of(context).size.height / 12,
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0, vertical: 3.0),
child: Row(
children: <Widget>[SizedBox(width: 5), Text("Text 1 ")],
),
),
Text("Text 2 "),
Expanded(
child: Text(
'Text which is very long and very very long indeed and getting things ready',
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold),
),
),
SizedBox(width: 5),
CircleAvatar(backgroundColor: Colors.black26),
],
),
);
I couldnt find why TextOwerflow.ellipsis gives error, but I handle my problem:
I find a widget that can do what I wanted the do, The widget name is Tooltip
I handle the text shorten problem with this code:
Tooltip(
message: userAction.route.name,
child: Text(
userAction.route.name.length < 10
? userAction.route.name
: userAction.route.name.substring(0, 10) + '...',
style: TextStyle(fontWeight: FontWeight.bold),
),
)

Flutter - Positioned Widget in Stack causing Exception

I'm getting the below exception when I try to encapsulate the PandemicCard with a Positioned widget. If I render the card lone/no Positioned widget, it works just fine.
I/flutter ( 7331): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter ( 7331): The following assertion was thrown during performLayout():
I/flutter ( 7331): RenderStack object was given an infinite size during layout.
I/flutter ( 7331): This probably means that it is a render object that tries to be as big as possible, but it was put
I/flutter ( 7331): inside another render object that allows its children to pick their own size.
I/flutter ( 7331): The nearest ancestor providing an unbounded height constraint is:
I/flutter ( 7331): RenderFlex#2b18c relayoutBoundary=up2 NEEDS-LAYOUT NEEDS-PAINT OVERFLOWING
I/flutter ( 7331): creator: Column ← Center ← MediaQuery ← LayoutId-[<_ScaffoldSlot.body>] ← CustomMultiChildLayout ←
For this code. Anyone able to help me figure out what I'm doing wrong?
class PandemicCard extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 120.0,
width: 76.0,
decoration: BoxDecoration(
color: Colors.blue,
boxShadow: [
BoxShadow(
blurRadius: 5.0,
color: Colors.grey)
]),
child: Text('Hi'),
);
}
}
class PandemicCardStackState extends State<PandemicCardStack> {
// final _cards = <PandemicCard>[ PandemicCard(), PandemicCard()];
final _cards = <PandemicCard>[ PandemicCard()];
#override
Widget build( BuildContext context) {
return Stack(
// This Bombs!
children: <Widget>[ Positioned( left: 0.0, top: 0.0, child: _cards[0])]
// This works!
// children: <Widget>[ _cards[0]]
);
}
}
class PandemicCardStack extends StatefulWidget {
#override
PandemicCardStackState createState() => PandemicCardStackState();
}
Add an empty Container as a child of the stack :
#override
Widget build( BuildContext context) {
return Stack(
children: <Widget>[
Container(),
Positioned( left: 0.0, top: 0.0, child: _cards[0]),
]
);
}
Other workarounds:
(a) Wrap the Stack on a Container with a known height:
Container(
height: 50,
child: Stack(
children: [
Positioned(top: 10, left: 10, child: Text('My child'))
]),
),
(b) As suggested add empty Container() and Clip.none:
Stack(
clipBehavior: Clip.none,
children: [
Container(),
Positioned(top: 10, left: 10, child: Text('My child'))
]),
Since this is still an issue. I also came across another option.
You can wrap your stack in an IntrinsicHeight widget as well.
IntrinsicHeight(
child:
Stack(
children: [Positioned(top: 10, left: 10, child:Text('My child')
)]
),
),

Flutter searchbar layout issue BoxConstraints forces an infinite width

I am trying to imitate a searchview similar to attached image, but I am getting following error. I can achieve this using ListTile but I can't set padding to the icons or TextField. So I am trying to achieve this using Row widget. Please have a look at my code and help me to draw this searchbar.
I/flutter (19181): The following assertion was thrown during
performLayout():
I/flutter (19181): BoxConstraints forces an infinite width.
I/flutter (19181): These invalid constraints were provided to
RenderAnimatedOpacity's layout() function by the
I/flutter (19181): following function, which probably computed
the invalid constraints in question:
I/flutter (19181): _RenderDecoration._layout.layoutLineBox (package:flutter/src/material/input_decorator.dart:767:11)
I/flutter (19181): The offending constraints were:
I/flutter (19181): BoxConstraints(w=Infinity, 0.0<=h<=46.0)
Here is my code:
new Container(
height: 70.0,
color: Theme.of(context).primaryColor,
child: new Padding(
padding: const EdgeInsets.all(8.0),
child: new Card(
child: new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Icon(Icons.search),
new Container(
height: double.infinity,
width: double.infinity,
child: new TextField(
controller: controller,
decoration: new InputDecoration(
hintText: 'Search', border: InputBorder.none),
// onChanged: onSearchTextChanged,
),
),
new IconButton(icon: new Icon(Icons.cancel), onPressed: () {
controller.clear();
// onSearchTextChanged('');
},),
],
),
)
))),
EDIT: This answer is a quick fix for the above question.
Best practice is Derek Lakin's answer
Answer:
To maximize container's width, set its width to
MediaQuery.of(context).size.width
Check this code:
new Container(
height: 70.0,
color: Theme.of(context).primaryColor,
child: new Padding(
padding: const EdgeInsets.all(8.0),
child: new Card(
child: new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Icon(Icons.search),
new Container(
//height: double.infinity, //This is extra
width: MediaQuery.of(context).size.width - 100.0, // Subtract sums of paddings and margins from actual width
child: new TextField(
controller: controller,
decoration: new InputDecoration(
hintText: 'Search', border: InputBorder.none),
// onChanged: onSearchTextChanged,
),
),
new IconButton(icon: new Icon(Icons.cancel), onPressed: () {
controller.clear();
// onSearchTextChanged('');
},),
],
),
)
)))
You're trying to define infinite height and width for the Container that is a parent of the TextField, which wants to use all the space.
The following works by using Expanded to fill the available space:
Container(
height: 70.0,
child: Card(
margin: EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.search),
),
Expanded(
child: TextField(
decoration: new InputDecoration(
hintText: 'Search', border: InputBorder.none),
),
flex: 1,
),
IconButton(
icon: Icon(Icons.cancel),
onPressed: () {},
)
],
),
),
),

Resources