Flutter - Scaffold with Appbar and listview - breaking with Expanded - flutter

I have an issue with Scaffold. I have an AppBar with text and a button. The body hosts a ListView.builder. Inside the ListView is a container and a number of TextButton Widgets.
The Text part of the TextButton can be wide, and causes the warning bar to appear. So, I wrapped in an Expanded widget to wrap it.
This results in an error...
The following assertion was thrown during performLayout(): RenderFlex
children have non-zero flex but incoming width constraints are
unbounded.
When a row is in a parent that does not provide a finite width
constraint, for example if it is in a horizontal scrollable, it will
try to shrink-wrap its children along the horizontal axis. Setting a
flex on a child (e.g. using Expanded) indicates that the child is to
expand to fill the remaining space in the horizontal direction. These
two directives are mutually exclusive. If a parent is to shrink-wrap
its child, the child cannot simultaneously expand to fit its parent.
Consider setting mainAxisSize to MainAxisSize.min and using
FlexFit.loose fits for the flexible children (using Flexible rather
than Expanded). This will allow the flexible children to size
themselves to less than the infinite remaining space they would
otherwise be forced to take, and then will cause the RenderFlex to
shrink-wrap the children rather than expanding to fit the maximum
constraints provided by the parent.
and also the contents of my AppBar disappear, and I can no longer click the back arrow.
Here is the scaffold to build the page...
late StateSetter _setState;
#override
Widget build(BuildContext context) {
return buildSubFormPage();
}
Widget buildSubPage() {
return StatefulBuilder(
builder: (bContext, StateSetter setBState) {
_setState = setBState;
return Scaffold(
appBar: new AppBar(
title: new Text("My list of items"),
actions: [
Padding(
padding: EdgeInsets.only(
right: 20.0),
child: openSubFormItem(
widget.field, 0,
"+ Add new", null),
)
],
),
body: ListView.builder(
padding: EdgeInsets.all(8.0),
//shrinkWrap: true,
itemCount: subFormItems.length,
itemBuilder: (context, index) {
return Container(
//width: screenWidth,
child: openSubFormItem(
widget.field, index, "Press Here",
subFormItems[index]),
);
},
)
);
}
);
}
Here is mostly the content of my openSubFormItem widget.
The building of the button text has been removed, but you can get the idea...
Widget openSubFormItem(PendigoFields field, int index, String buttonText, dynamic subFormItem) {
String outputText = "A long string of text, that will surely cause the warning bars if I can't make it wrap properly";
if (buttonText == "+ Add new") {
outputText = buttonText;
}
return Container(
//padding: EdgeInsets.all(4),
//width: screenWidth - 30,
child:
TextButton(
child: Row(
mainAxisSize: MainAxisSize.max,
//mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Flexible(
// fit : FlexFit.loose,
// child: Text(outputText, style: TextStyle(color: Colors.black,
// fontSize: 15.0,
// fontWeight: FontWeight.bold,),),
// ),
Expanded(child: Text(outputText, style: TextStyle(color: Colors.black,
fontSize: 15.0,
fontWeight: FontWeight.bold,),),
),
// Text(outputText, style: TextStyle(color: Colors.black,
// fontSize: 15.0,
// fontWeight: FontWeight.bold,),),
// I also have an IconButton here, removed for clarity
]
),
)
decoration: buttonText == "Press Here" ? BoxDecoration(
border: Border(
bottom: BorderSide(color: Colors.purple[400]!)),
)
: null
);
}
How do I get my AppBar to show the AppBar content (and button) and allow my ListView to be able to wrap the text if the text is too long?

As the error says: unbounded width, this is because the Row parent which is the TextButton does not have a specified width, and when using Expanded, the Row or the Column parent of it must know its constrains.
Give a width to the TextButton.
Also a note, don't create your widgets using methods as this is not recommend from flutter team, use separated widgets instead.

Related

How to prevent OverFlow of the Trailing widget using Column widget to occupy all the children elements inside of a ListTile widget?

How to prevent OverFlow of the Trailing widget using Column widget to occupy all the children elements inside of a ListTile widget ?
Thanks and appreiciate you help.
body: ListView.builder(
restorationId: 'sampleItemListView',
itemCount: items.length,
itemBuilder: (BuildContext context, int index) {
final item = items[index];
return Padding(
padding: const EdgeInsets.only(top: 8, left: 8, right: 8),
child: Container(
color: Colors.grey.shade400,
height: 200,
child: ListTile(
isThreeLine: true,
leading: const CircleAvatar(
// Display the Flutter Logo image asset.
foregroundImage:
AssetImage('assets/images/flutter_logo.png'),
),
title: Text('Title ${item.id}'),
subtitle: Text('Subtitle ${item.id}'),
How to expand the column in the Trailing component of the
ListTile to prevent Overflow?
trailing: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
Icon(
Icons.emoji_emotions,
color: Colors.green,
),
Icon(
Icons.emoji_emotions,
color: Colors.orange,
),
Icon(
Icons.emoji_emotions,
color: Colors.red,
),
],
),
onTap: () {
Navigator.restorablePushNamed(
context,
SampleItemDetailsView.routeName,
);
}),
),
);
},
),
ERROR:
════════ Exception caught by rendering library ═════════════════════════════════
A RenderFlex overflowed by 16 pixels on the bottom.
The relevant error-causing widget was
Column
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.
In your case there r many answers like
1: ListTile( visualDensity: VisualDensity(vertical: 4))
2: ListTile(
trailing: FittedBox(
child: Column( children: const [Icon(),Icon(),Icon()]),
),
)
** But best solution in my opinion, In such extensive cases use "Row" than "ListTile" it gives u way more control over ur UI widgets.

flutter unbounded width of TextField in a Stack widget: An InputDecorator, which is typically created by a TextField, cannot have an unbounded width

Flutter:
I am trying to make a todo list app. So I have used Stack widget with two children ListView and a Row widget positioned at the bottom with Positioned widget. I want the Row to contain a TextField and a IconButton wrapped with a SizedBox.
Now what I want is to align the IconButton to bottom-right corner and the TextField to take all the available space. this code I have tried.
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
// TODO: ListView here
Positioned(
bottom: 0.0,
child: Row(
children: [
// child #1
const Expanded(
child: TextField(
decoration: InputDecoration(
hintText: "Type here"
),
),
),
// child #2
SizedBox(
height: 30.0,
width: 30.0,
child: IconButton(
icon: const Icon(Icons.send),
onPressed: () {},
),
),
],
),
),
],
),
);
}
this code throws this error.
The following assertion was thrown during performLayout():
RenderFlex children have non-zero flex but incoming width constraints are unbounded.
When a row is in a parent that does not provide a finite width constraint, for example if it is in a horizontal scrollable, it will try to shrink-wrap its children along the horizontal axis. Setting a flex on a child (e.g. using Expanded) indicates that the child is to expand to fill the remaining space in the horizontal direction.
These two directives are mutually exclusive. If a parent is to shrink-wrap its child, the child cannot simultaneously expand to fit its parent.
Consider setting mainAxisSize to MainAxisSize.min and using FlexFit.loose fits for the flexible children (using Flexible rather than Expanded). This will allow the flexible children to size themselves to less than the infinite remaining space they would otherwise be forced to take, and then will cause the RenderFlex to shrink-wrap the children rather than expanding to fit the maximum constraints provided by the parent.
now I set mainAxisSize of Row to MainAxisSize.min and flex of Flexible widget to FlexFit.loose.
Positioned(
bottom: 0.0,
child: Row(
mainAxisSize: MainAxisSize.min, // added this
children: [
// child #1
const Flexible(
fit: FlexFit.loose, // added this
child: TextField(
decoration: InputDecoration(
hintText: "Type here"
),
),
),
// child #2
SizedBox(
height: 30.0,
width: 30.0,
child: IconButton(
icon: const Icon(Icons.send),
onPressed: () {},
),
),
],
),
),
but getting this error now.
The following assertion was thrown during performLayout():
An InputDecorator, which is typically created by a TextField, cannot have an unbounded width.
This happens when the parent widget does not provide a finite width constraint. For example, if the InputDecorator is contained by a Row, then its width must be constrained. An Expanded widget or a SizedBox can be used to constrain the width of the InputDecorator or the TextField that contains it.
'package:flutter/src/material/input_decorator.dart':
Failed assertion: line 959 pos 7: 'layoutConstraints.maxWidth < double.infinity'
Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=2_bug.md
If I don't use the Stack then its fine. But I have to. Now what should I do?
If a widget is wrapped in a [Positioned], then it is a positioned widget in its [Stack]. If the [right] property is non-null, the right edge of this child will be positioned [right] layout units from the right of the stack widget. The [left], [bottom], and [top] properties work analogously.
So, if you set [right] to 0.0 and [left] to 0.0, it means that
[stack] will force the child to have a particular width. in this case the full width of the screen.
Just add this 2 lines of code to achieve what you want.
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
// TODO: ListView here
Positioned(
bottom: 0.0,
left: 0.0, <----------- (1)
right: 0.0, <----------- (2)
child: Row(
children: [
// child #1
const Expanded(
child: TextField(
decoration: InputDecoration(
hintText: "Type here"
),
),
),
// child #2
SizedBox(
height: 30.0,
width: 30.0,
child: IconButton(
icon: const Icon(Icons.send),
onPressed: () {},
),
),
],
),
),
],
),
);
}

How to display a screen which contains of an Icon on top half and ListView on bottom half?

I want to display a mock-up streaming screen like this:
Top half is the video player (showing the speaker), and bottom half is a ListView displaying participants/subscribers list.
Here's my code:
import 'package:flutter/material.dart';
import 'common.dart';
class StreamingView extends StatelessWidget {
// Display a Participant item
Widget getParticipantView(Participant item) {
return Container(
padding: EdgeInsets.all(10.0),
child: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
item.name,
style: TextStyle(fontSize: 14, color: Colors.black54),
),
),
Expanded(
child: CircleAvatar(backgroundColor: Colors.blue),
),
],
));
}
// Display the participants list on a ListView
Widget getParticipantsListView(List<Participant> participantsList){
//#override
// Widget build(BuildContext context) {
return Container (
//Expanded()
height: 40,
child: ListView.builder(
itemCount: participantsList.length,
itemBuilder: (context, index){
return getParticipantView(participantsList[index]);
}
)
);
//}
}
#override
Widget build(context) {
List<Participant> theList = [
Participant(name: "Jack", description:"Away"),
Participant(name:"Paul", description:"Available"),
Participant(name:"Clive", description:"Available"),
Participant(name:"Frank", description:"Available")
];
return Scaffold(
appBar: AppBar(),
body: Container(
padding: EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Image.asset('assets/generic_portrait.jpg'),
Expanded(
flex: 1,
child: getParticipantsListView(theList)
),
],
)),
floatingActionButton: FloatingActionButton(
onPressed: () async {
print("The button is clicked...");
},
child: Icon(Icons.video_call)));
}
}
I ran it, and the result is this:
The speaker can be seen, but the participants list isn't. Turns out there's an exception:
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY
╞═════════════════════════════════════════════════════════ The
following assertion was thrown during performLayout(): RenderFlex
children have non-zero flex but incoming height constraints are
unbounded. When a column is in a parent that does not provide a finite
height constraint, for example if it is in a vertical scrollable, it
will try to shrink-wrap its children along the vertical axis. Setting
a flex on a child (e.g. using Expanded) indicates that the child is to
expand to fill the remaining space in the vertical direction. These
two directives are mutually exclusive. If a parent is to shrink-wrap
its child, the child cannot simultaneously expand to fit its parent.
Consider setting mainAxisSize to MainAxisSize.min and using
FlexFit.loose fits for the flexible children (using Flexible rather
than Expanded). This will allow the flexible children to size
themselves to less than the infinite remaining space they would
otherwise be forced to take, and then will cause the RenderFlex to
shrink-wrap the children rather than expanding to fit the maximum
constraints provided by the parent. ... ... The relevant error-causing
widget was: Column
file:///C:/Users/anta40/Flutter/streamingtest/streaming.dart:11:16
That refers to child: Column( inside Widget getParticipantView().
How to fix this?
you can use stack , the parent maybe use column after that the stack will be the first , after that use a listview which can hold all the participants
Have you tried using Shrink-wrap in ListView.builder and remove the container with Static height.
The hight is unbound because you're using Expanded widget in the column. Remove the Expanded widget that is wrapping the CircleAvatar. Here's your code:
// Display a Participant item
Widget getParticipantView(Participant item) {
return Container(
padding: EdgeInsets.all(10.0),
child: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
item.name,
style: TextStyle(fontSize: 14, color: Colors.black54),
),
),
CircleAvatar(backgroundColor: Colors.blue),
],
));
}

Overflowed container with WebView on flutter

How to fix the bottom overflowed by WebView into a Container()? The _getDescription method is into a Column Widget and Expanded Widget but the it is overflowed the container().
The _getDescription method is returning a WebView instance from HtmlWidget plugin. My code:
Widget _getBody(tittle, date, description, origin, context) {
return new Container(
margin: new EdgeInsets.all(15.0),
child: Expanded(
child: new Column(
children: <Widget>[
_getTittle(tittle),
_getDate(date, origin),
_getDescription(description),
_getImageGallery(),
],
),
),
);
}
_getDescription(description) {
return new Container(
margin: new EdgeInsets.only(top: 20.0, bottom: 4.0),
child: HtmlWidget(
description,
textStyle: TextStyle(fontSize: 15.5),
webView: true,
),
);
}
Result:
Try to use SingleChildScrollView(child: Column(...)) instead of Expanded()
There are multiple ways to solve this issue. You can use replace the Expanded widget with SingleChildScrollView. Another way is to use ListView.
Or, if you don't want to scroll the overflowed text, use overflow: TextOverflow.ellipsis inside the Text widget on the _getDescription method

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.