I have the following where when I run it, I get the following error:
RenderFlex children have non-zero flex but incoming height constraints
are unbounded. RenderBox was not laid out: RenderRepaintBoundary#ad336
NEEDS-LAYOUT NEEDS-PAINT
The issue seems to be coming from my ListView.builder.
The general suggestion from past questions such as ListView.builder gives error: RenderBox was not laid out
has been to wrap it in an Expanded widget which I have done. But I am still seeing above error.
Could I please get some advice as to what I am doing wrong please. Thanks.
Pasting the whole file here in case there is some red herring going on.
The Expanded and ListView.builder section is at the end.
import 'package:flutter/material.dart';
import 'account_details.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Color(0xff020B2A),
appBar: AppBar(
backgroundColor: Color(0xff020B2A),
centerTitle: true,
title: Column(
children: [
Text(
'Account',
style: TextStyle(
fontSize: 12,
),
),
Text(
'Card Ending - 00000',
style: TextStyle(
fontSize: 9,
letterSpacing: 1.1,
),
),
],
),
actions: [
Padding(
padding: const EdgeInsets.only(right: 8),
child: Icon(Icons.messenger_outline),
),
],
),
body: Column(
children: [
Center(
child: Column(
children: [
SizedBox(height: 30),
Text('Good Evening', style: TextStyle(
color: Colors.white,
fontSize: 12,
),),
SizedBox(height: 18),
Text('NAME', style: TextStyle(
color: Colors.white,
fontSize: 28,
),),
SizedBox(height: 18),
Text('Member Since \'18\'', style: TextStyle(
color: Colors.white70,
fontSize: 10,
),),
],
),
),
Column(
children: [
SizedBox(height: 30),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.only(left: 16.0, bottom: 16.0),
child: Text('Account', style: TextStyle(
color: Colors.white70,
fontSize: 16,
),),
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true, // added after suggestion. same error
itemCount: accountTitles.length,
itemBuilder: (context, index) {
return ListTile(
onTap: (){},
leading: Icon(accountTitles[index].leadingIcon),
title: Text(accountTitles[index].title),
trailing: Icon(accountTitles[index].trailingIcon),
);
},
),
),
],
),
],
),
),
);
}
}
The test data accountTitles coming from following:
import 'package:flutter/material.dart';
class Info {
final String title;
final IconData leadingIcon;
final IconData trailingIcon;
Info({this.title, this.leadingIcon, this.trailingIcon});
}
List<Info> accountTitles = [
Info(title: 'A', leadingIcon: Icons.chevron_left, trailingIcon: Icons.chevron_right),
Info(title: 'B', leadingIcon: Icons.chevron_left, trailingIcon: Icons.chevron_right),
Info(title: 'C', leadingIcon: Icons.chevron_left, trailingIcon: Icons.chevron_right),
];
Your scrollable (ListView in this case) is rendered inside two nested Column so the general advice (use Expanded) is correct but you need to do it twice: both for the inner column and the list view. See it in action here https://dartpad.dev/855cbaf9d055104a04824b0f3bb5413d?null_safety=true
Related
I have ListView.builder which returns ExpansionTile. Inside of this ExpansionTile, I used trailing with row widget. When I use row inside of the trailing, I lost the animation effect, therefore I used AnimatedRotation widget. But now every other ExpansionTile's trailing icon changes its direction.
Is there any way to prevent this behaviour? I just want the animate the trailing icon of the ExpansionTile that I pressed to change.
Note: I aim to put trailing with text and icon with proper turn animation. If there are any other solutions rather than using trailing with row I am open to recommendations.
Here is my code
ListView.builder(
itemCount: 15,
itemBuilder: (context, index) {
return ExpansionTile(
iconColor: Colors.red,
textColor: Colors.grey.shade900,
childrenPadding: EdgeInsets.symmetric(horizontal: 0, vertical: 0),
expandedCrossAxisAlignment: CrossAxisAlignment.stretch,
tilePadding: EdgeInsets.symmetric(
vertical: 0,
horizontal: 10,
),
leading: Icon(Icons.ac_unit),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text("60.00₺"),
AnimatedRotation(
turns: _isExpanded ? .5 : 0,
duration: Duration(milliseconds: 200),
child: Icon(Icons.expand_more)),
],
),
onExpansionChanged: (value) {
setState(() {
_isExpanded = value;
});
},
title: Text(
"22.04.2022",
style: TextStyle(
fontSize: 20,
color: Color(AppColors.blacktextcolor),
fontWeight: FontWeight.bold),
),
subtitle: Text("Bekliyor"),
children: <Widget>[
ListTile(
title: Text(
"Talep Eden",
style: TextStyle(color: Colors.grey, fontSize: 13),
),
subtitle: Text(
"Sertan Yıldız",
style: TextStyle(color: Colors.blue, fontSize: 18),
),
),
],
);
},
),
https://gifyu.com/image/S3J5c
you need to store the state of the expanded widgets in a list.
Generate a list with a false or true state for all expansion tiles and then use that state based on the index for each tile.
Take a look at the following code below:
class MyWidget extends StatefulWidget {
const MyWidget({Key? key}) : super(key: key);
#override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
List<bool> _isExpandedStateList =
List<bool>.generate(15, (int index) => false);
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 15,
itemBuilder: (context, index) {
bool _isExpanded = _isExpandedStateList[index];
return ExpansionTile(
iconColor: Colors.red,
textColor: Colors.grey.shade900,
childrenPadding: EdgeInsets.symmetric(horizontal: 0, vertical: 0),
expandedCrossAxisAlignment: CrossAxisAlignment.stretch,
tilePadding: EdgeInsets.symmetric(
vertical: 0,
horizontal: 10,
),
leading: Icon(Icons.ac_unit),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text("60.00₺"),
AnimatedRotation(
turns: _isExpanded ? .5 : 0,
duration: Duration(milliseconds: 200),
child: Icon(Icons.expand_more)),
],
),
onExpansionChanged: (value) {
setState(() {
_isExpandedStateList[index] = value;
});
},
title: Text(
"22.04.2022",
style: TextStyle(
fontSize: 20,
color: Colors.blue,
fontWeight: FontWeight.bold),
),
subtitle: Text("Bekliyor"),
children: <Widget>[
ListTile(
title: Text(
"Talep Eden",
style: TextStyle(color: Colors.grey, fontSize: 13),
),
subtitle: Text(
"Sertan Yıldız",
style: TextStyle(color: Colors.blue, fontSize: 18),
),
),
],
);
},
);
}
}
Let me know if you have any doubts.
I have a widget that builds a list from an array. Each item in the array builds a widget with some columns and rows. I want the text to break so It doesnt overflow.
I've tried adding overflow: TextOverflow.ellipsis to the Text or wrapping the Row that wraps the icon and the text that overflow with a Expanded widget, but both didn't work.
Actually it looks like this:
This is my code:
child: Column(
verticalDirection: VerticalDirection.down,
textBaseline: TextBaseline.alphabetic,
textDirection: TextDirection.ltr,
children: < Widget > [
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: < Widget > [
Row(
children: [
const Icon(Icons.medication),
//
// This is the text that overflows
//
Text(
entries[index].pillname,
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
],
),
Text(
entries[index].pillTimeStr,
style: const TextStyle(
fontSize: 28,
color: Color.fromARGB(255, 79, 79, 79),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: < Widget > [
Container(
margin: const EdgeInsets.all(4),
child: FloatingActionButton(
onPressed: () {
setState(() {
entries[index].pilldone = !entries[index].pillDone;
});
},
tooltip:
entries[index].pillDone ? 'Tomada' : 'No tomada',
backgroundColor: entries[index].pillDone ?
Colors.green :
Theme.of(context).primaryColor,
child: const Icon(Icons.check),
),
),
Container(
margin: const EdgeInsets.all(4),
child: FloatingActionButton(
onPressed: () {
showAdaptiveActionSheet(
context: context,
cancelAction: CancelAction(
title: const Text('Cancelar'),
),
actions: < BottomSheetAction > [
BottomSheetAction(
title: const Text('Modificar'),
onPressed: () {}),
BottomSheetAction(
title: const Text('Eliminar'),
onPressed: () {
Navigator.pop(context);
_askRemovePill(entries[index].iD);
}),
]);
},
tooltip: 'Eliminar',
backgroundColor: Colors.blue,
child: const Icon(Icons.mode_edit),
)),
],
),
],
),
In your case, all you need to do is wrap your Text inside the Row with an Expanded widget
Expanded(
child: Text(/*......your text widget........*/),
),
The Expanded widget gives your Text widget horizontal constraints
IF you don't wish to see the text go on to the next line,
use the overflow property on the text
overflow : TextOverflow.ellipsis, //inside Text
Use the Wrap widget instead of the Row widget. It will break the text to the next line should there be an overflow.
Like this,
Wrap(
children: [
const Icon(Icons.medication),
//
// This is the text that overflows
//
Text(
entries[index].pillname,
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
],
),
Text(
entries[index].pillTimeStr,
style: const TextStyle(
fontSize: 28,
color: Color.fromARGB(255, 79, 79, 79),
),
),
],
),
I'm currently building products from my store in my products screen, What I'm attempting to do is, create a GridView and a card for each product. I'm having problem with the overflow from the image.
What I want to look like:
How it is going:
My code for the card:
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:loja_virtual_nnananene/helpers/color_select.dart';
import 'package:loja_virtual_nnananene/models/product.dart';
class ProductListTile extends StatelessWidget {
const ProductListTile(this.product);
final Product product;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).pushNamed('/product', arguments: product);
},
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
alignment: Alignment.center,
children: [Image.network(product.images!.first)],
),
Text(
product.name,
style: GoogleFonts.firaCode(
textStyle:
TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
),
Text('R\$ ${product.basePrice.toStringAsFixed(2)}',
style: GoogleFonts.firaCode(
textStyle: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w800,
color: ColorSelect.cprice)))
],
),
));
}
}
Try to add your Card Widget inside SingleChildScrollView() Widget :
SingleChildScrollView(
child:Card(),
),
There is no need Stack widget in your code. Try this:
If you want u can remove ConstrainedBox, but image size will be different according to its size.
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:loja_virtual_nnananene/helpers/color_select.dart';
import 'package:loja_virtual_nnananene/models/product.dart';
class ProductListTile extends StatelessWidget {
const ProductListTile(this.product);
final Product product;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).pushNamed('/product', arguments: product);
},
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ConstrainedBox(
constraints: const BoxConstraints(
minHeight: 50.0,
maxHeight:300.0
),
child: Image.network(product.images!.first),
),
Text(
product.name,
style: GoogleFonts.firaCode(
textStyle:
TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
),
Text('R\$ ${product.basePrice.toStringAsFixed(2)}',
style: GoogleFonts.firaCode(
textStyle: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w800,
color: ColorSelect.cprice)))
],
),
));
}
}
Are you using SliverGridDelegateWithFixedCrossAxisCount? If yes, it has a property aspectRatio which is default to 1.0 (height will be same as width). Try to make it 0.7 or something and your error will be gone in that case.
You can achieve the first image this way
Container(
decoration: Boxdecoration(
color: Colors.white,
borderRadius: borderRadius.circular(8),
boxShasow: [
BoxShadow(
offset: Offset(10,17),
blurRadius:17,
spreadRadius: -23,
color: Colors.grey,),],),
child: Padding(
padding: const EdgeInset.all(10.0),
child: Column(
Image.network(
"your url",
width: width of choice,
height: height of choice,
),
Text(
"product name",
testAlign:TestAlign.left,
style:(your style),
),
Row(
children:<Widget>[
Text(
"product amount",
testAlign:TestAlign.left,
style:(your style),
),
Expanded(
child:Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Icon(
Icons.heart_outlind,
color:Colors.blue,
size:24,
),
SizedBox(width:5),
],),),
],),),),
I need to add another item to my list in a flutter app. The problem comes in the children: quotes.map((quote) => quoteTemplate(quote)).toList() part. I have tried adding a text widget after it to try and test it. However, I constantly get error. The error says I cannot add list to Widgets. My full code is.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import "quote.dart";
void main() => runApp(MaterialApp(
home: QuoteList(),
));
class QuoteList extends StatefulWidget {
#override
_QuoteListState createState() => _QuoteListState();
}
class _QuoteListState extends State<QuoteList> {
int index = 1;
List <Quote> quotes = [
Quote(text: "1. It always seems impossible until it's done.", author: "Nelson Mandela", date: "1954"),
Quote(text: "2. Don't watch the clock; do what it does. Keep going.", author: "Sam Levenson", date: "1985"),
Quote(text: "3. Live life to the fullest, and focus on the positive.", author: "Matt Cameron", date: "1965"),
];
Widget quoteTemplate(quote) {
return Card(
margin: EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0),
elevation: 5,
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
quote.text,
style: TextStyle(
fontSize: 18.0,
color: Colors.grey[600],
),
),
SizedBox(height: 17.0),
Text(
quote.author,
style: TextStyle(
fontSize: 11.0,
color: Colors.grey[700],
),
),
SizedBox(height: 17.0),
Text(
quote.date,
style: TextStyle(
fontSize: 11.0,
color: Colors.grey[750],
),
),
],
),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Quote App",
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
centerTitle: true,
backgroundColor: Colors.green,
),
backgroundColor: Colors.white,
body:
Center(
child: Column(
children: quotes.map((quote) => quoteTemplate(quote)).toList(),
//quotes.map((quote) => quoteTemplate(quote)).toList().toString(),
),
),
);
}
}
You can append to an existing list using the ... syntax:
Column(
children: [
...quotes.map((quote) => quoteTemplate(quote)).toList(),
Text(),
Text(),
],
),
I've stuck with one problem.
I'm a novice with a flutter trying to figure out how to do a simple swipe-left/swipe-right gallery.
I'm looking for a widget that supports gestures and some kind of overflow.
So I want a container with a fixed(width/height which I can define) and everything outside of this container should be hidden and when user swipes inner content it should show the next slide. Can you please point me out what is the best way to implement this with a Flutter and what is the best kind of containers fit these goals. Thanks
UPD 1:
It shouldn't be a whole screen, but a specific container.
You just need to use the PageView widget for the viewpager functionality , you can use it horizontal or vertical as your requirement,As you want horizontal PageView so i have used the scrollDirection: Axis.horizontal for it. I have created the demo of it, please check it once
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class HomeScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _HomeScreen();
}
}
class _HomeScreen extends State<HomeScreen> {
static final GlobalKey<ScaffoldState> _scaffoldKey =
GlobalKey<ScaffoldState>();
///Page Controller for the PageView
final controller = PageController(
initialPage: 0,
);
#override
Widget build(BuildContext context) {
Size _screenSize = MediaQuery.of(context).size;
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
centerTitle: true,
title: Text(
'Horizontal Viewpager',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,),
),
),
///A Page View with 3 children
body: PageView(
controller: controller,
scrollDirection: Axis.horizontal,
physics: BouncingScrollPhysics(),
pageSnapping: true,
children: <Widget>[
Container(
color: Colors.white,
child: Card(
color: Colors.lightBlue,
elevation: 4,
margin: EdgeInsets.all(24),
child: Center(
child: Text(
"Card 1",
style: TextStyle(
color: Colors.white,
fontSize: 24),
),
),
),
),
Container(
color: Colors.white,
child: Card(
color: Colors.purpleAccent,
elevation: 4,
margin: EdgeInsets.all(24),
child: Center(
child: Text(
"Card 2",
style: TextStyle(
color: Colors.white,
fontSize: 24),
),
),
),
),
Container(
color: Colors.white,
child: Card(
color: Colors.pink,
elevation: 4,
margin: EdgeInsets.all(24),
child: Center(
child: Text(
"Card 3",
style: TextStyle(
color: Colors.white,
fontSize: 24),
),
),
),
),
],
),
);
}
}
And output of above program as follow
You can check my another example where i have created the swipable with fixed height Click here
I am posting another example, as you need the indicator at the both side of the PagewView for it , you need to use the Row with Expaned as follow
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class HomeScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _HomeScreen();
}
}
class _HomeScreen extends State<HomeScreen> {
static final GlobalKey<ScaffoldState> _scaffoldKey =
GlobalKey<ScaffoldState>();
var selectedPage = 0;
PageController _controller = PageController(initialPage: 0, keepPage: true);
#override
Widget build(BuildContext context) {
Size _screenSize = MediaQuery
.of(context)
.size;
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
centerTitle: true,
title: Text(
'Horizontal Viewpager',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,),
),
),
///A Page View with 3 children
body: Container(
child:Container(
height: MediaQuery.of(context).size.height*0.4,
child: Row(
children: <Widget>[
Expanded(
flex: 1,
child:
IconButton(
icon: Icon(Icons.arrow_back),
highlightColor: Colors.pink,
onPressed: () {
setState(() {
if (selectedPage > 0) {
selectedPage = selectedPage - 1;
_controller.jumpToPage(selectedPage);
print("VALUES==>>>>> $selectedPage");
}
});
},
),
), Expanded(
flex: 8,
child: PageView(
controller: _controller,
scrollDirection: Axis.horizontal,
physics: BouncingScrollPhysics(),
onPageChanged: (index)
{
selectedPage= index;
},
pageSnapping: true,
children: <Widget>[
Container(
color: Colors.white,
child: Card(
color: Colors.lightBlue,
elevation: 4,
margin: EdgeInsets.all(24),
child: Center(
child: Text(
"Card 1",
style: TextStyle(
color: Colors.white,
fontSize: 24),
),
),
),
),
Container(
color: Colors.white,
child: Card(
color: Colors.purpleAccent,
elevation: 4,
margin: EdgeInsets.all(24),
child: Center(
child: Text(
"Card 2",
style: TextStyle(
color: Colors.white,
fontSize: 24),
),
),
),
),
Container(
color: Colors.white,
child: Card(
color: Colors.pink,
elevation: 4,
margin: EdgeInsets.all(24),
child: Center(
child: Text(
"Card 3",
style: TextStyle(
color: Colors.white,
fontSize: 24),
),
),
),
),
],
),
),
Expanded(
flex: 1,
child:
IconButton(
icon: Icon(Icons.arrow_forward),
highlightColor: Colors.pink,
onPressed: () {
if (selectedPage <3) {
selectedPage = selectedPage + 1;
_controller.jumpToPage(selectedPage);
print("VALUES==>> $selectedPage");
}
},
),
)
],
),
)
,
)
,
);
}
}
Please check the below output of it
You can use carousel_slider 2.1.0 package.
It also has many customisation options.
https://pub.dev/packages/carousel_slider