Stack within ListView fails Flutter - flutter

I am trying to add a Stack within a ListView in a SafeArea. However, there is a runtime exception as seen below:
BoxConstraints forces an infinite height.
I/flutter (18717): These invalid constraints were provided to RenderConstrainedBox's layout() function by the following
I/flutter (18717): function, which probably computed the invalid constraints in question:
I/flutter (18717): RenderConstrainedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:259:13)
I/flutter (18717): The offending constraints were:
I/flutter (18717): BoxConstraints(w=411.4, h=Infinity)
My code:
#override
Widget build(BuildContext context) {
SizeConfig().init(context);
return new Scaffold(
body: SafeArea(
top: true,
child: ListView( shrinkWrap: true,
children: <Widget>[_buildFrostedRow(context)])));
}
Stack _buildFrostedRow(BuildContext context) {
return Stack(
children: <Widget>[
new ConstrainedBox(
constraints: const BoxConstraints.expand(), child: _showCardRow()),
new Center(
child: new ClipRect(
child: new BackdropFilter(
filter: new ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: new Container(
width: SizeConfig.safeBlockHorizontal * 90,
height: SizeConfig.safeBlockVertical * 20,
decoration: new BoxDecoration(
color: Colors.grey.shade200.withOpacity(0.5)),
child: new Center(
child: new Text('Frosted',
style: Theme.of(context).textTheme.display3),
),
),
),
),
),
],
);
}
What am I missing here?

You need to limit height to Stack (put it into Container and set height or something like that). Because if you didn't, the ListView cannot calculate layout.
return new Scaffold(
body: SafeArea(
top: true,
child: ListView( shrinkWrap: true,
children: <Widget>[Container(height:200, // can change
child: _buildFrostedRow(context))])));

Just wrap your Stack with Constrained box or Fixed Heigh Container.
Because, Listview and Stack has infinite height

Related

Flutter - Size missing error on TextField

When using TextField inside a container that is centered by a parent row widget. No parents have a defined width. Container is supposed to take width of the content inside it.
Error - parentData: offset=Offset(0.0, 0.0); id=_ScaffoldSlot.body (can use size) constraints: BoxConstraints(0.0<=w<=1920.0, 0.0<=h<=924.0) size: MISSING behavior: opaque
My stateless widget:
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Pangea')),
body: Container(
color: Colors.black45,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: double.infinity,
// width: double.infinity,
child: Column(
children: [
TextField(
// decoration: InputDecoration(
// constraints: BoxConstraints.tightFor(
// width: 300,
// ),
// ),
),
],
)),
],
),
),
),
);
}
If I use InputDecoration inside TextField it works fine. But I would like to keep its size dynamic. May be perhaps I can specify min and max width .
I think you might need IntrinsicHeight widget.
It makes its child to wait until its parent has a defined Height and, with that value in its hands, builds the child.

Widgets render in debug, but not in release

In one of my Flutter files I have this code that theoretically doesn't seem it should be a problem to run at all. It renders nicely in the debug version but when I build a release iOS and Android app files, it becomes partly invisible. There's a widget that renders called _heyName() which is just a text widget. The _whatWouldYouLike() widget is pretty much a 1:1 copy of the _heyName() one, yet this one doesn't render and neither does any widget afterwards.
Console does throw this warning though:
======== Exception caught by widgets library =======================================================
The following assertion was thrown while applying parent data.:
Incorrect use of ParentDataWidget.
The ParentDataWidget Flexible(flex: 1) wants to apply ParentData of type FlexParentData to a RenderObject, which has been set up to accept ParentData of incompatible type ParentData.
Usually, this means that the Flexible widget has the wrong ancestor RenderObjectWidget. Typically, Flexible widgets are placed directly inside Flex widgets.
The offending Flexible is currently placed inside a RepaintBoundary widget.
The ownership chain for the RenderObject that received the incompatible parent data was:
ConstrainedBox ← Container ← Flexible ← RepaintBoundary ← IndexedSemantics ← NotificationListener<KeepAliveNotification> ← KeepAlive ← AutomaticKeepAlive ← KeyedSubtree ← SliverList ← ⋯
When the exception was thrown, this was the stack:
#0 RenderObjectElement._updateParentData.<anonymous closure> (package:flutter/src/widgets/framework.dart:5723:11)
#1 RenderObjectElement._updateParentData (package:flutter/src/widgets/framework.dart:5739:6)
#2 RenderObjectElement.attachRenderObject (package:flutter/src/widgets/framework.dart:5761:7)
#3 RenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5440:5)
#4 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6082:11)
...
====================================================================================================
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
pinned: false,
expandedHeight: appBarHeight,
automaticallyImplyLeading: false,
floating: true,
flexibleSpace: LayoutBuilder(
builder: (context, constraints) {
return Container(
alignment: Alignment.bottomCenter,
child: Container(
height: SizeConfig.screenWidth * 0.13,
child: GestureDetector(
onTap: () {
},
child: _searchCategories(context))),
);
},
),
),
];
},
body: ListView(
shrinkWrap: true,
children: [
_heyName(),
SizedBox(
height: 10,
),
_whatWouldYouLike(),
SizedBox(
height: 10,
),
_requests(),
SizedBox(
height: 10,
),
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_categoriesText(),
_seeAll(),
],
),
SizedBox(
height: SizeConfig.screenWidth * 0.03,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_category("Food and Beverages", 1),
_category("Design", 2),
],
),
SizedBox(
height: SizeConfig.screenWidth * 0.1,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_category("Music", 3),
_category("Sports and Fitness", 4),
],
),
SizedBox(
height: SizeConfig.screenWidth * 0.1,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_category("Personal Grooming", 5),
_category("Information Technology", 6),
],
),
SizedBox(
height: SizeConfig.screenWidth * 0.1,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_category("Home Services", 7),
_category("Lifestyle", 8),
],
),
SizedBox(
height: SizeConfig.screenWidth * 0.1,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_category("Pet Services", 9),
_category("Consulting", 10),
],
),
SizedBox(
height: SizeConfig.screenWidth * 0.25,
),
],
),
],
),
),
);
}
}
Is there any other widget I could use instead of ListView here? I feel like that's the source of the problem as when I use a Column instead of ListView, it renders fine, just because it's bigger than the screen, it throws the good old RenderFlex error. I tried putting the Column in Expanded, but no luck. I feel I'm missing something here.
It's probably being caused by one of your custom widgets like _heyName() or _whatWouldYouLike().
Share the code for those widgets, or better to look into the code you wrote, and make sure they don't start with a Flexible widget.
The error is self explanatory, You are using a Flexible widget inside something besides a Row or Column. So in your listView, the children start with a Flexible, and thus, you get this error. Same goes for Expanded, you can't put an Expanded inside a container or listview for example.

SingleChildScrollView with Column of Flexible Cards: "A RenderFlex Overflowed by x pixels on bottom", How to make card expand?

I'm trying to make a list of cards that are displayed in a SingleChildScrollView.
However I can't figure out how to make the cards fit their contents.
I've attached a picture of my issue, and how I want the cards to look like.
I've tried putting them in an expanded which doesn't seem to make a difference.
I've also tried setting a manual height on the card container which for some reason only displays two cards and doesn't let me scroll.
I'm presuming that I need to set a minimum height on the cards, but I can't seem to figure out at what level should I add it.
Widget displayVideo(item) {
return Flexible(
child: Container(
child: Card(
child: Column(
children: <Widget>[
ListTile(
leading: CircleAvatar(
backgroundImage:
NetworkImage(item.fromChannel.channelThumbnail),
),
title: Text(item.fromChannel.channelTitle),
subtitle: Text(item.publishAt),
),
Container(
child: new AspectRatio(
aspectRatio: 16 / 10,
child: new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
fit: BoxFit.fitWidth,
alignment: FractionalOffset.center,
image: new NetworkImage(item.thumbnailUrl),
)),
),
),
),
Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
item.title,
style: TextStyle(color: Colors.black, fontSize: 16),
),
),
)
],
),
),
),
);
}
Widget displayVideos(items) {
List<Widget> lines = [];
print(items);
items.videos.forEach((element) => lines.add(displayVideo(element)));
return SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: Column(children: lines)));
}
#override
Widget build(BuildContext context) {
final ExplorePlaylistArguments args =
ModalRoute.of(context).settings.arguments;
playlist = fetchPlaylist(args.playlistId);
return Scaffold(
appBar: AppBar(
title: Text(args.playlistName),
),
body: Container(
child: FutureBuilder<Playlist>(
future: playlist,
builder: (context, snapshot) {
if (snapshot.hasData) {
return displayVideos(snapshot.data);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return Center(child: CircularProgressIndicator());
}),
));
}
════════ Exception caught by rendering library ═════════════════════════════════════════════════════
The following assertion was thrown during layout:
A RenderFlex overflowed by 303 pixels on the bottom.
The relevant error-causing widget was:
Column file:///C:/Users/Jonathan/AndroidStudioProjects/klp_app/lib/screens/explore_playlist.dart:29:18
The overflowing RenderFlex has an orientation of Axis.vertical.
The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the RenderFlex to fit within the available space instead of being sized to their natural size.
This is considered an error condition because it indicates that there is content that cannot be seen. If the content is legitimately bigger than the available space, consider clipping it with a ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex, like a ListView.
The specific RenderFlex in question is: RenderFlex#42b06 relayoutBoundary=up19 OVERFLOWING
... parentData: <none> (can use size)
... constraints: BoxConstraints(0.0<=w<=384.7, 0.0<=h<=67.9)
... size: Size(384.7, 67.9)
... direction: vertical
... mainAxisAlignment: start
... mainAxisSize: max
... crossAxisAlignment: center
... verticalDirection: down
◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤
════════════════════════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by rendering library ═════════════════════════════════════════════════════
A RenderFlex overflowed by 303 pixels on the bottom.
How the cards look like:
How I want each individual card to look like:
Solution:
Widget displayVideo(item) {
return Card(
child: Column(
children: <Widget>[
ListTile(
leading: CircleAvatar(
backgroundImage:
NetworkImage(item.fromChannel.channelThumbnail),
),
title: Text(item.fromChannel.channelTitle),
subtitle: Text(item.publishAt),
),
new AspectRatio(
aspectRatio: 16 / 9,
child: Image.network(item.thumbnailUrl, fit:BoxFit.fitWidth),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
item.title,
style: TextStyle(color: Colors.black, fontSize: 16),
),
)
],
),
);
}
Widget displayVideos(items) {
List<Widget> lines = [];
items.forEach((element) => lines.add(displayVideo(element)));
return SingleChildScrollView(
child: Column(children: lines));
}
Tip: You can also use ListView.builder() instead of SingleChildScrollView and Column
You have to remove Container from displayVideos method.
return SingleChildScrollView(child: Column(children: lines)); // container remove
And remove Flexible from displayVideo method.

children have non-zero flex but incoming height constraints are unbounded

return Card(
child: Row(
children: <Widget>[
Placeholder(
fallbackHeight: 100,
fallbackWidth: 100,
),
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(height: 10, child: Container(child: Text("One"),)),
Expanded(child: Container(child: Text("Center") )),
],
)
],
),
);
On the code above I am getting error:
I/flutter ( 4872): The following assertion was thrown during performLayout():
I/flutter ( 4872): RenderFlex children have non-zero flex but incoming height constraints are unbounded.
I/flutter ( 4872): When a column is in a parent that does not provide a finite height constraint, for example if it is
I/flutter ( 4872): in a vertical scrollable, it will try to shrink-wrap its children along the vertical axis. Setting a
I/flutter ( 4872): flex on a child (e.g. using Expanded) indicates that the child is to expand to fill the remaining
I/flutter ( 4872): space in the vertical direction.
Whole code:
class FilmItems extends StatelessWidget {
List<String> filmListList;
List<String> _getFilmList() {
var items = List<String>.generate(101, (counter) => "item $counter");
return items;
}
FilmItems() {
filmListList = _getFilmList();
}
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: filmListList.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Row(
children: <Widget>[
Placeholder(
fallbackHeight: 100,
fallbackWidth: 100,
),
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(height: 10, child: Container(child: Text("One"),)),
Expanded(child: Container(child: Text("Center") )),
],
)
],
),
);
});
}
}
What is wrong?
The problem is that you are using Expanded and any of it's parents have an explicit height.
The solution would depend on how do you want to handle the height of the Expanded. In your case, seems to be that you want to have a Row with a fixed height equal to the Placeholder. In that case, you need to wrap the Row with the same height as the Placeholder, like this:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("")),
body: ListView.builder(
itemCount: 3,
itemBuilder: (BuildContext context, int index) {
return Card(
child: SizedBox(
height: 100,
child: Row(
children: <Widget>[
Placeholder(
fallbackHeight: 100,
fallbackWidth: 100,
),
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text("One"),
Expanded(child: Center(child: Text("Center"))),
],
),
],
),
),
);
}),
);
}
I removed the height 10 of the Text("One") because if the fontSize is bigger, the text would look cropped. And I wrapped the Text("Center") with a Center widget, I think that's what you wanted to achieve.
Suggestion: If the content inside the Row could haven a bigger height than the Row, the content would look cropped. If that could happen you might want to take another approach.
When you are using Column widget, it's parent should have a finite height. So in your code the parent is a row and it also does not have a finite height. You need wrap Column with Container and give a finite height.
Container(
height: 500,
child: Column()
)
Put your Column/Row inside an Expanded or SizedBox (with some height) like this:
Expanded(
child: Column(...)
)
Or
SizedBox(
height: 250, // give some height
child: Column(...),
)

How to create a horizontally scrolling table with fixed column in Flutter?

I would like to create a series of tables that you can scroll through vertically, each of which may have a different number of rows/columns from each other.
Within each table, I would like to have the leftmost column frozen in place, and the remaining columns in that table to be horizontally scrollable, in case there are a number of columns that do not fit in the width of the screen. See screenshot:
My initial plan was to use a ListView for the page-level vertical scrolling between tables, and within each table, there is a Row of Columns, where the first column is a static width, and the remaining columns are enclosed within a horizontally scrolling ListView. The error I'm getting from Flutter is not helping me determine what I need to do, but it clearly has to do with having to set bounds on child Widgets.
Error: (Fixed 7/9/19 by wrapping horizontal ListView with a fixed height container and shrinkwrapping the ListView)
The following assertion was thrown during performResize():
Horizontal viewport was given unbounded width.
Viewports expand in the scrolling direction to fill their container.In this case, a horizontal
viewport was given an unlimited amount of horizontal space in which to expand. This situation
typically happens when a scrollable widget is nested inside another scrollable widget.
If this widget is always nested in a scrollable widget there is no need to use a viewport because
there will always be enough horizontal space for the children. In this case, consider using a Row
instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
the width of the viewport to the sum of the widths of its children.
New Error 7/9/19:
The following message was thrown during layout:
A RenderFlex overflowed by 74 pixels on the right.
The overflowing RenderFlex has an orientation of Axis.horizontal.
The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
RenderFlex to fit within the available space instead of being sized to their natural size.
This is considered an error condition because it indicates that there is content that cannot be
seen. If the content is legitimately bigger than the available space, consider clipping it with a
ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex,
like a ListView.
The specific RenderFlex in question is:
RenderFlex#9bf67 relayoutBoundary=up5 OVERFLOWING
creator: Row ← RepaintBoundary-[<0>] ← IndexedSemantics ←
NotificationListener ← KeepAlive ← AutomaticKeepAlive ← SliverList ←
SliverPadding ← Viewport ← IgnorePointer-[GlobalKey#74513] ← Semantics ← Listener ← ⋯
parentData: (can use size)
constraints: BoxConstraints(w=404.0, 0.0<=h<=Infinity)
size: Size(404.0, 300.0)
direction: horizontal
mainAxisAlignment: start
mainAxisSize: max
crossAxisAlignment: center
textDirection: ltr
This was the issue I ran into originally before getting side-tracked with the first issue reported; I can't understand why my ListView is not creating a scrollable container.
Code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
home: Scaffold(
appBar: AppBar(
title: Text('My App'),
backgroundColor: Colors.teal[400],
),
body: MyClass(),
),
);
}
}
const double headerCellWidth = 108.0;
const double cellPadding = 8.0;
const double focusedColumnWidth = 185.0;
const double rowHeight = 36.0;
class MyClass extends StatefulWidget {
#override
_MyClassState createState() => _MyClassState();
}
class _MyClassState extends State<MyClass> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return ListView(
padding: EdgeInsets.all(5.0),
children: <Widget>[
Row(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
color: Colors.grey,
padding: EdgeInsets.all(cellPadding),
width: headerCellWidth,
),
HeaderCell('ABC'),
HeaderCell('123'),
HeaderCell('XYZ'),
],
),
Container(
height: 300.0, // Could compute height with fixed rows and known number of rows in advance
child: ListView(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children: <Widget>[
Column(
children: <Widget>[
Container(
color: Colors.grey[300],
padding: EdgeInsets.all(cellPadding),
height: rowHeight,
width: focusedColumnWidth,
),
NumberCell('89'),
NumberCell('92'),
NumberCell('91'),
NumberCell('90'),
NumberCell('91'),
NumberCell('89'),
],
),
Column(
children: <Widget>[
Container(
color: Colors.grey[300],
padding: EdgeInsets.all(cellPadding),
height: rowHeight,
width: focusedColumnWidth,
),
NumberCell('89'),
NumberCell('92'),
NumberCell('91'),
NumberCell('90'),
NumberCell('91'),
NumberCell('89'),
],
),
],
),
),
],
),
],
);
}
}
class HeaderCell extends StatelessWidget {
HeaderCell(this.text);
final String text;
#override
Widget build(BuildContext context) {
return Container(
height: rowHeight,
padding: EdgeInsets.all(cellPadding),
width: headerCellWidth,
child: Text(
text,
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
);
}
}
class NumberCell extends StatelessWidget {
NumberCell(this.text);
final String text;
#override
Widget build(BuildContext context) {
return Container(
height: rowHeight,
width: focusedColumnWidth,
padding: EdgeInsets.all(cellPadding),
child: Text(
text,
),
);
}
}
Here is a quick example and this would be the result: Video
List<Widget> _buildCells(int count) {
return List.generate(
count,
(index) => Container(
alignment: Alignment.center,
width: 120.0,
height: 60.0,
color: Colors.white,
margin: EdgeInsets.all(4.0),
child: Text("${index + 1}", style: Theme.of(context).textTheme.title),
),
);
}
List<Widget> _buildRows(int count) {
return List.generate(
count,
(index) => Row(
children: _buildCells(10),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: _buildCells(20),
),
Flexible(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: _buildRows(20),
),
),
)
],
),
),
);
}
So I tried to produce a minimum working bit of code, and ended up with a workable solution (even if all the details aren't ironed out, like the first locked column being of flexible width instead of a fixed width as desired). Hopefully this will help others trying to produce something similar. What's interesting is that the Table construct is needed here, because replacing the TableRow (wrapped by Table) with just a Row causes an overflow error. I would still be interested in understanding why that is since it seems crucial to the layout engine.
#override
Widget build(BuildContext context) {
return ListView(
padding: EdgeInsets.all(5.0),
children: <Widget>[
Table(
children: <TableRow>[
TableRow(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// first locked column items
],
),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
// table header items
],
),
Row(
children: <Widget>[
// data cells
],
),
Row(
children: <Widget>[
// data cells
],
),
],
),
),
],
),
],
),
],
);
}
If there is not much customization needed, for those needed a fixed header and first column table may also consider to use the horizontal_data_table package:
https://pub.dev/packages/horizontal_data_table
It basically is using the two list view approach.