I'm reseaching now for more hours and don't get why it's not possible to put an image and a card with a bunch of ListTiles in a Row.
The error what im getting is:
The following assertion was thrown during performLayout():
BoxConstraints forces an infinite width.
The offending constraints were:
BoxConstraints(w=Infinity, 0.0<=h<=Infinity)
But i dont really get what exactly has to be in a Box should it be the Card with the ListTiles?
Can someone help me with this?
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child:
/* card == null
? loadCards()
: ListTile() */
SingleChildScrollView(
child: Card(
child: Row(mainAxisSize: MainAxisSize.min, children: [
Image.network(
"widget.card.imageUrl",
loadingBuilder: (BuildContext context, Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null) {
return child;
}
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.red,
),
);
},
),
Card(
child: Column(mainAxisSize: MainAxisSize.min, children: [
ListTile(
trailing: Icon(Icons.play_arrow),
title: Text("Black Lotus"),
subtitle: Text("Name"),
),
Container(
child: Row(
children: [Icon(Icons.play_arrow), Icon(Icons.polymer)],
),
),
ListTile(
title: Text("Hello"),
),
ListTile(
title: Text("Hello"),
),
]),
),
]),
),
),
),
);
}
Wrap Card with Expanded/Flexible which will solve your constraint problem, Also it's very important to give image width, as at remaining space you are putting other widgets.
return Scaffold(
appBar: AppBar(
title: Text('Sample'),
),
body: SingleChildScrollView(
child: Card(
child: Row(mainAxisSize: MainAxisSize.min, children: [
Image.network(
"https://cdn.pixabay.com/photo/2018/07/11/21/51/toast-3532016_1280.jpg",
width: 40,
loadingBuilder: (BuildContext context, Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null) {
return child;
}
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.red,
),
);
},
),
Expanded(
child: Card(
child: Column(mainAxisSize: MainAxisSize.min, children: [
ListTile(
trailing: Icon(Icons.play_arrow),
title: Text("Black Lotus"),
subtitle: Text("Name"),
),
Container(
child: Row(
children: [Icon(Icons.play_arrow), Icon(Icons.polymer)],
),
),
ListTile(
title: Text("Hello"),
),
ListTile(
title: Text("Hello"),
),
]),
),
),
]),
),
),
);
Your ListTile needs constraints so it knows where its bounds are.
Just give it some constraints (eg. by wrapping in a SizedBox with a width) or, if you want to take it as much space as possible, just wrap each ListTile with a Flex widget such as Flexible or Expanded if you want to share space evenly with all tiles on that Column.
Related
I will explain with simple examble,
class Demo1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: [
Flexible(
child: ListView(
shrinkWrap: true,
children: const [
ListTile(
leading: Icon(Icons.image),
title: Text('with shrinkwrap is true'),
trailing: Icon(Icons.delete_forever),
),
])),
Expanded(
child: Container(
color: Colors.green,
)),
],
),
),
);
}
}
Here the green colored container is not filling the remaining space, so how to fill the remaining area?
Thanks in advance
Try below code and just Remove your first Flexible Widget
Column(
children: <Widget>[
ListView(
shrinkWrap: true,
children: const [
ListTile(
leading: Icon(Icons.image),
title: Text('with shrinkwrap is true'),
trailing: Icon(Icons.delete_forever),
),
],
),
Expanded(
child: Container(
color: Colors.green,
),
),
],
),
You can use SingleChildScrollView instead of using ListView with shrinkWrap: true.
class Demo1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: [
SingleChildScrollView(
child: Column(
children: const [
ListTile(
leading: Icon(Icons.image),
title: Text('with shrinkwrap is true'),
trailing: Icon(Icons.delete_forever),
),
],
),
),
Expanded(
child: Container(
color: Colors.green,
)),
],
),
),
);
}
}
You may also like CustomScrollView over SingleChildScrollView and shrinkWrap:true.
Both Flexible and Expanded have flex value 1, so they both request 50% of the available space. So the Container child of Expanded takes fills only half space, while the ListView, a child of Flexible, also requests half the space but needs very little space.
You can make Container fill the available space by removing Flexible, so Expanded that wraps Container will get all the available space.
Hello everyone I want to dispaly some informations inside scaffold but I got
The relevant error-causing widget was: Scaffold.
Even when I remove it I still got errors:
this is the code :
Widget build(BuildContext context) {
return Scaffold(
body: ExpansionTile(
title: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
widget.model.name,
overflow: TextOverflow.ellipsis,
),
Text(
widget.model.id.toString(),
style: Theme.of(context).textTheme.caption,
)
],
),
leading: SingleChildScrollView(
child: Column(
// children: [
// Text(widget.model.mtu.toString()),
children: <Widget>[
StreamBuilder(
stream: widget.model.mtu,
initialData: 0,
builder: (c, snapshot) => ListTile(
title: const Text('MTU Size'),
subtitle: Text('${snapshot.data} bytes'),
),
// ],
),
],
),
),
trailing: TextButton(
onPressed: () {
setState(() {
buttonText = 'Connecting...';
});
widget.viewModel.establishConnectAndEnableNotify(widget.model);
},
child: Text(
buttonText,
style: TextStyle(color: AppColors.blue),
).tr(),
)));
}
}
I would be very thankful if you can help me
The issue occurring because of using ListTile, it is trying to get infinite width. You can wrap it with SizedBox and provide width. Using LayoutBuilder on top level will be better to get the parent widget width.
return Scaffold(
body: LayoutBuilder(
builder: (_, constraints) => ExpansionTile(
title: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[],
),
leading: SingleChildScrollView(
child: Column(
// children: [
// Text(widget.model.mtu.toString()),
children: <Widget>[
StreamBuilder(
// stream: "widget.model.mtu",
initialData: 0,
builder: (c, snapshot) => SizedBox(
width:
constraints.maxWidth * .2, //depend on you or hard-coded value
child: ListTile(
title: Text(' w ${constraints.maxWidth}'),
subtitle: Text('${snapshot.data} bytes'),
),
),
// ],
),
],
),
),
Also, I think you don't want to have SingleChildScrollView on leading, maybe you like to use it on children
I am a new flutter developer.I try to make listview to view a set of data that comes from the database.The list now works, but as follows:
Now it is not presented separately.I need to display every element in the card.An example of what I'm trying to do:
In this picture, each item on the card is separate and separated from the second.How I can do it?If anyone knows the solution please help me.
my code now like that:
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
child: Card(
child :FutureBuilder<List<Flowerdata>>(
future: fetchFlowers(),
builder: (context, snapshot) {
if (!snapshot.hasData) return Center(
child: CircularProgressIndicator()
);
return ListView(
children: snapshot.data
.map((data) => Column(children: <Widget>[
GestureDetector(
onTap: ()=>{
getItemAndNavigate(data.id, context)
},
child: Row(
children: [
Container(
width: 100,
height: 100,
margin: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child:
Image.network(data.flowerImageURL,
width: 200, height: 100, fit: BoxFit.cover,))),
Flexible(child:
Text(data.flowerName,
style: TextStyle(fontSize: 18))
),
]),),
Divider(color: Colors.black),
],
))
.toList(),
);
},
)
),
),
]
)
);
}
You need to wrap your item's Column(not the FutureBuilder) in with Card
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: <Widget>[
Expanded(
child: FutureBuilder<List<Flowerdata>>(
future: fetchFlowers(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(child: CircularProgressIndicator());
return ListView(
children: snapshot.data
.map((data) => Card(
child: Column(
children: <Widget>[
GestureDetector(
onTap: () => {getItemAndNavigate(data.id, context)},
child: Row(children: [
Container(
width: 100,
height: 100,
margin: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.network(
data.flowerImageURL,
width: 200,
height: 100,
fit: BoxFit.cover,
))),
Flexible(
child: Text(data.flowerName,
style: TextStyle(fontSize: 18))),
]),
),
Divider(color: Colors.black),
],
),
))
.toList(),
);
},
),
),
]));
}
Setup
Start a new Flutter project. I'm calling mine flutter_listview.
Open main.dart and replace the code with the following:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'ListViews',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: Scaffold(
appBar: AppBar(title: Text('ListViews')),
body: BodyLayout(),
),
);
}
}
class BodyLayout extends StatelessWidget {
#override
Widget build(BuildContext context) {
return _myListView(context);
}
}
// replace this function with the code in the examples
Widget _myListView(BuildContext context) {
return ListView();
}
Note the _myListView() function at the end. You will be replacing this with the code in the examples below
Basic types of ListViews
Static ListView
If you have a short list of items that don't change, then you can use the default ListView constructor to make it. This is useful for making something like a settings menu page.
Replace _myListView() with the following:
Widget _myListView(BuildContext context) {
return ListView(
children: <Widget>[
ListTile(
title: Text('Sun'),
),
ListTile(
title: Text('Moon'),
),
ListTile(
title: Text('Star'),
),
],
);
}
Run the app and you should see the following image. (After this when refreshing, usually hot reload works fine, but I find at times I need to do a hot restart or even completely stop and restart the app.)
ListTile customization
The Flutter team designed the ListTile widget to handle the normal content that you would want in a list. This means that most of the time there is no need to define a custom layout. You can just use the default ListTile for each item in the list. When we made a ListView in the example above we only used the title option. But we can also show subtitles, images, and icons.
Replace _myListView() with the following
Widget _myListView(BuildContext context) {
return ListView(
children: <Widget>[
ListTile(
leading: Icon(Icons.wb_sunny),
title: Text('Sun'),
),
ListTile(
leading: Icon(Icons.brightness_3),
title: Text('Moon'),
),
ListTile(
leading: Icon(Icons.star),
title: Text('Star'),
),
],
);
}
The leading is for adding an icon or image at the start of the ListTile.
You can also add an icon at the end if you specify the trailing attribute.
ListTile(
leading: Icon(Icons.wb_sunny),
title: Text('Sun'),
trailing: Icon(Icons.keyboard_arrow_right),
)
The right arrow icon makes it look like the list items are clickable, but they aren't. Not yet. We will see how to add touch events in the next section. It's easy. (Hint: onTap )
Instead of icons, we can also use images. The recommended image option is to use a CircleAvatar widget.
Replace _myListView() with the following:
Widget _myListView(BuildContext context) {
return ListView(
children: <Widget>[
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage('assets/sun.jpg'),
),
title: Text('Sun'),
),
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage('assets/moon.jpg'),
),
title: Text('Moon'),
),
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage('assets/stars.jpg'),
),
title: Text('Star'),
),
],
);
}
If you want MASTERING FLUTTER LISTVIEWS enter link description here
I am trying to show a listview after some texts in a column. The text shows properly inside the first Row until I add a listview inside the next row. Everything disappears after adding the ListView.
Here is the Code:
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text(
"Prayer Time",
style: TextStyle(fontSize: 20, fontWeight:
FontWeight.normal),
),
],
),
Row(
children: <Widget>[myList()],
),
],
),
),
floatingActionButton: FloatingActionButton(
tooltip: 'Add Alarm',
child: Icon(Icons.add),
backgroundColor: const Color(0xff0A74C5),
),
);
}
Expanded myList() {
return Expanded(
child: ListView.builder(
itemBuilder: (context, position) {
return Card(
child: Text(androidVersionNames[position]),
);
},
itemCount: androidVersionNames.length,
)
);
}
}
change like this:
Expanded(
child: Row(
children: <Widget>[myList()],
),
),
Your ListView should have a fixed Size. Try to wrap the ListView inside a Container.
I run your code and fixed it. Replace your myList() with this code bellow:
Expanded myList() {
return Expanded(
child: Container(
width: double.infinity,
height: 200,
child: ListView.builder(
itemBuilder: (context, position) {
return Card(
child: Text(androidVersionNames[position]),
);
},
itemCount: androidVersionNames.length,
),
)
);
}
I need to have some structure like this
I use LayoutBuilder to get the height of content (between App Bar and TabsBottomNavigation). Here i build Profile Info Container and want to build ListView with some List Tiles, but when I try to build it in Layout Builder I have errors in console.
If I create ListView out of LayoutBuilder it works!
Please help me to solve it.
My code below:
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Container(
height: viewportConstraints.maxHeight * .44,
color: Theme.of(context).primaryColor,
padding: EdgeInsets.only(bottom: 2),
child: Align(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildProfileImage(context),
SizedBox(height: 17),
Text(userName)
],
),
),
),
Expanded(
child: ListView(
children: <Widget>[
ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
)
],
),
)
],
),
),
);
},
);
}
Use below build method will work in your case. (I have checked and it's working, so I hope it will work in your case also and will fit in your requirement.)
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return Container(
child: Column(
children: <Widget>[
Container(
height: viewportConstraints.maxHeight * .44,
color: Theme.of(context).primaryColor,
padding: EdgeInsets.only(bottom: 2),
child: Align(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildProfileImage(context),
SizedBox(height: 17),
Text(userName),
],
),
),
),
SizedBox(height: 16),
Flexible(
child: ListView(
children: <Widget>[
Card(
child: ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
),
),
],
),
),
],
),
);
},
);
}
I think SingleChildScrollView is of no use in this case so I removed it but you can use it if you fill so.
You still need to do some UI improvement as per your wish as this is the basic structure as per your requirement.
Hope this will help you.
You are using the LayoutBuilder in a wrong way.
It's supposed to be used to change the layout with the size of the device and/or orientation.
What you are trying to do is best accomplished with MediaQuery:
MediaQuery.of(context).padding.top //APP bar height
MediaQuery.of(context).padding.bottom //Bottom bar height
MediaQuery.of(context).size.height //Screen height
Widget build(BuildContext context) {
return Column(
children:<Widget>[
Expanded(
child:LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Container(
height: viewportConstraints.maxHeight * .44,
color: Theme.of(context).primaryColor,
padding: EdgeInsets.only(bottom: 2),
child: Align(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildProfileImage(context),
SizedBox(height: 17),
Text(userName)
],
),
),
),
Expanded(
child: ListView(
children: <Widget>[
ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
)
],
),
)
],
),
),
);
},
),
),
]
);
}
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ListView(
shrinkWrap: true,
children: <Widget>[
new Container(
height: MediaQuery.of(context).size.height/3,
color: Theme.of(context).primaryColor,
padding: EdgeInsets.only(bottom: 2),
child: Align(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildProfileImage(context),
SizedBox(height: 17),
Text(userName)
],
),
),
),
new ListView(
shrinkWrap: true,
children: <Widget>[
ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
)
],
)
],
),
);
},
);
}
If you read the error log, it says non-zero flex incoming but constraints are unbounded. To understand that clearly, imagine Flutter is trying to draw pixels of something that not finite. That's the our problem.
Widgets like ListView or SingleChildScrollView are flex widgets and has no limits unlike Column or Row.
If you have children that sizes are not definite, then you have to define flex for your ListView. For that, you can use shrinkWrap or Flexible, Expanded widgets for both ListView itself or children.
And here is the my solution, simplified as much as possible:
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return ListView(
shrinkWrap: true, // That's it
children: <Widget>[
Container(
color: Theme.of(context).primaryColor,
height: viewportConstraints.maxHeight * .44,
padding: EdgeInsets.only(bottom: 2),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildProfileImage(context),
SizedBox(height: 17),
Text(userName)
],
),
),
ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
),
ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
),
ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
)
],
);
},
);
}
Meanwhile, you have too many children that does nothing. If you want different scrolling behavior inside the Profile Info and ListTiles parts, tell me because we will must create yet another ListView for achieve that.
Also if you share your buildProfileImage widget, we can optimize your code even further, because you may even not need the LayoutBuilder widget in this case.