I have created a ListTile to return all my documents from my collection in Firestore. But I want to put "R$" before the number, not above it:
Is there a way to do it? Also, I would like to know if there is how to put more information before the ListTile. When I try to create a Text, it gives me an error:
This is the code:
class FinancasMensais extends StatefulWidget {
const FinancasMensais({super.key});
#override
State<FinancasMensais> createState() => _FinancasMensaisState();
}
class _FinancasMensaisState extends State<FinancasMensais> {
final _fireStore = FirebaseFirestore.instance;
final ref =
FirebaseFirestore.instance.collection('addsaidas').snapshots();
Future<void> getData() async {
QuerySnapshot querySnapshot =
await _fireStore.collection('addsaidas').get();
final allData = querySnapshot.docs.map((doc) => doc.data()).toList();
for (var dataMap in allData) {
if (dataMap is Map) {
for (var key in dataMap.keys) {
print('$key: ${dataMap[key]}');
}
print('----------------------');
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromARGB(255, 92, 172, 178),
centerTitle: true,
title: Text('Finanças Mensais'),
toolbarHeight: 90,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40)
),
elevation: 15,
),
body: StreamBuilder<QuerySnapshot>(
//child: Center(child: Text('Todo Task'),),
stream: ref,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
}
final documents = snapshot.data!.docs;
return ListView.builder(
itemCount: documents.length,
itemBuilder: (context, index) {
final document = documents[index];
final data = document.data() as Map<String, dynamic>;
return ListTile(
contentPadding: EdgeInsets.only(left: 15, right: 15, top: 15, bottom: 4),
leading: Icon(Icons.where_to_vote_outlined,
color: Colors.pink,
size: 36,
),
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(data['nomesaida'],
style: TextStyle(
fontSize: 22,
),),
Text(data['tipocategoria']),
],
),
trailing: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text("R\$",
style: TextStyle(
fontSize: 15
),
),
Text(data['valorsaida'] as String,
style: TextStyle(
color: Colors.pink,
fontSize: 28,
),),
Text(data['datasaida'],
style: TextStyle(
color: Colors.pink
),),
],
),
dense: false,
);
},
);
},
),
);
}
}
Let me outline what you want to do with the above code:
Put specific text before the number
Add text before List Tile Widget
Let's talk about where you may be wrong with your approach.
You are coding both the specific text and number separately. To avoid doing this you should add both fields in a single Text Widget like this(assuming there are no styling constraints):
Text('R\$ ${data['valorsaida']}',
style: TextStyle(
color: Colors.pink,
fontSize: 28,
),
),
Assuming you have styling constraints to adhere to, try using RichText Widget.
To add information before ListTile, try using Column:
// return column instead of ListTile like this:
return Column(
mainAxisSize: MainAxisSize.min,
children: [
//Your Text here
Center(child: Text('Todo Task')),
//Your ListTile here
ListTile(...),
],
);
Hope this helps you.
Duda!
The R$ is above the number cause you're putting all of them inside a Column - that aligns the children always vertically.
To make the R$ appears at the left of the number, you can wrap both inside a Row.
// const Text(
// "R\$",
// style: TextStyle(fontSize: 15),
// ),
// Text(
// data['valorsaida'] as String,
// style: const TextStyle(
// color: Colors.pink,
// fontSize: 28,
// ),
// ),
/// Put it inside a row to align horizontally
Row(
/// Align the children to the right.
mainAxisAlignment: MainAxisAlignment.end,
/// Make the row as small as possible.
/// If you don't do this, the row will take up the entire width of the screen.
/// And you'll get a flutter exception.
mainAxisSize: MainAxisSize.min,
children: [
const Text(
"R\$",
style: TextStyle(fontSize: 15),
),
Text(
(data['valorsaida'] as num).toString(),
style: const TextStyle(
color: Colors.pink,
fontSize: 28,
),
),
],
),
But you can also use the intl library to format currency for you. Give a try to that.
Related
I got this error while running the app. I not so advanced in flutter yet. Trying to find solutions. Can u guys help me please?
Error: Could not find the correct Provider above this Consumer Widget
This happens because you used a BuildContext that does not include the provider
of your choice. There are a few common scenarios:
You added a new provider in your main.dart and performed a hot-reload.
To fix, perform a hot-restart.
The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
You used a BuildContext that is an ancestor of the provider you are trying to read.
Make sure that Consumer is under your MultiProvider/Provider.
This usually happens when you are creating a provider and trying to read it immediately.
For example, instead of:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// Will throw a ProviderNotFoundError, because `context` is associated
// to the widget that is the parent of `Provider<Example>`
child: Text(context.watch<Example>().toString()),
);
}
consider using builder like so:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// we use `builder` to obtain a new `BuildContext` that has access to the provider
builder: (context, child) {
// No longer throws
return Text(context.watch<Example>().toString());
}
);
}
My code here below
import 'package:flutter/material.dart';
class CartModel extends ChangeNotifier {
// list of items on sale
final List _shopItems = const [
// [ itemName, itemPrice, imagePath, color ]
["Avocado", "4.00", "lib/images/avocado.png", Colors.green],
["Banana", "2.50", "lib/images/banana.png", Colors.yellow],
["Chicken", "12.80", "lib/images/chicken.png", Colors.brown],
["Water", "1.00", "lib/images/water.png", Colors.blue],
];
// list of cart items
final List _cartItems = [];
get cartItems => _cartItems;
get shopItems => _shopItems;
// add item to cart
void addItemToCart(int index) {
_cartItems.add(_shopItems[index]);
notifyListeners();
}
// remove item from cart
void removeItemFromCart(int index) {
_cartItems.removeAt(index);
notifyListeners();
}
// calculate total price
String calculateTotal() {
double totalPrice = 0;
for (int i = 0; i < cartItems.length; i++) {
totalPrice += double.parse(cartItems[i][1]);
}
return totalPrice.toStringAsFixed(2);
}
}
//another page
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'cart_model.dart';
class CartPage extends StatelessWidget {
const CartPage({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle:true,
title: const Text("My Cart",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
backgroundColor: Colors.green[600],
elevation: 0,
iconTheme: IconThemeData(
color: Colors.grey[800],
),
),
body: Consumer<CartModel>(
builder: (context, value, child) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Let's order fresh items for you
// list view of cart
Expanded(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: ListView.builder(
itemCount: value.cartItems.length,
padding: const EdgeInsets.all(12),
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(12.0),
child: Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(8)),
child: ListTile(
leading: Image.asset(
value.cartItems[index][2],
height: 36,
),
title: Text(
value.cartItems[index][0],
style: const TextStyle(fontSize: 18),
),
subtitle: Text(
"\$" + value.cartItems[index][1],
style: const TextStyle(fontSize: 12),
),
trailing: IconButton(
icon: const Icon(Icons.cancel),
onPressed: () =>
Provider.of<CartModel>(context, listen: false)
.removeItemFromCart(index),
),
),
),
);
},
),
),
),
// total amount + pay now
Padding(
padding: const EdgeInsets.all(36.0),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.green,
),
padding: const EdgeInsets.all(24),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Total Price',
style: TextStyle(color: Colors.green[200]),
),
const SizedBox(height: 8),
// total price
Text(
'\$${value.calculateTotal()}',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
],
),
// pay now
Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.green.shade200),
borderRadius: BorderRadius.circular(28),
),
padding: const EdgeInsets.all(12),
child: Row(
children: const [
Text(
'Pay Now',
style: TextStyle(color: Colors.white),
),
Icon(
Icons.arrow_forward_ios,
size: 16,
color: Colors.white,
),
],
),
),
],
),
),
)
],
);
},
),
);
}
}
I have a DefaultTabController with two pages nested in a scaffold. In my scaffold's App Bar is a save button and I want this button to return a value to a previous page, based on a variable that is calculated in one of the tabs. How do I get this value?
Here is my DefaultTabController
DefaultTabController(
initialIndex: index,
length: 2,
child: Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: AppBar(
elevation: 0,
backgroundColor: fumigruen_accent,
leading: CloseButton(
color: Colors.black,
onPressed: () {
Navigator.of(context).pop();
},
),
actions: buildEditingActions(),
),
body: Column(children: [
tabBar(),
Expanded(
child: TabBarView(children: [
//1st Tab
GewichtsrechnerEinfach(),
//2nd Tab
Column()
]),
)
]),
));}
And here is the save-Button I want to use to pass a varaible to the previous screen
List<Widget> buildEditingActions() => [
ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: fumigruen_accent,
elevation: 0,
foregroundColor: Colors.black,
),
onPressed: () {
Navigator.of(context).pop(gewicht);
},
icon: Icon(Icons.save),
label: Text("Speichern"))
];
The tabbar Code
Widget tabBar() => TabBar(
labelColor: Theme.of(context).primaryColor,
indicatorColor: Theme.of(context).primaryColor,
labelStyle: TextStyle(fontWeight: FontWeight.bold),
tabs: [
Tab(
child: Row(mainAxisSize: MainAxisSize.min, children: [
Icon(
Icons.assessment_outlined,
),
SizedBox(
width: 5,
),
Text("Einfach")
]),
),
Tab(
child: Row(mainAxisSize: MainAxisSize.min, children: [
Icon(
Icons.addchart,
),
SizedBox(
width: 5,
),
Text("Fortgeschritten")
]),
),
]);
and an extract of the GewichtsrechnerEinfach():
class _GewichtsrechnerEinfachState extends State<GewichtsrechnerEinfach> {
final _formKey = GlobalKey<FormState>();
num koerperlaenge = 0;
num brustumfang = 0;
var _koerperlaengeControler = TextEditingController();
var _brustumfangControler = TextEditingController();
num gewicht = 0;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//{two textinput fields setting the variables koerperlaenge and brustumfang are here}
Center(
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
decoration: ThemeHelper().buttonBoxDecoration(context),
child: ElevatedButton(
style: ThemeHelper().buttonStyle(),
child: Padding(
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Text(
"berechnen".toUpperCase(),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
onPressed: () async {
if (_formKey.currentState!.validate()) {
setState(() {
gewicht = Gewichtskalkulator().einfach(
brustumfang.toDouble(),
koerperlaenge.toDouble());
});
}
}),
),
),
],
),
),
),
);
}
The variable "gewicht" is calculated and changed in the first tab "GewichtsrechnerEinfach". So how do I get the changed variable to this main screen so that I can use it while saving?
Thanks a lot :)
As I found out by chatting in comments section, you are changing a value in a Page and you want to use it in another pages or screen, this is why you should use StateManagement something like Provider.
As you said you need to change the gewicht variable and use it where ever you want.
step 1) please add provider: ^6.0.5 (or any version that is compatible) in your pubspec.yaml and call flutter pub get.
step 2) now you should create a provider class to make all the variables that you want to use everywhere, alive. please create a dart file named:
gewichtsrechner_einfach_provider.dart
step 3) now you should put these codes in you provider class:
import 'package:flutter/material.dart';
class GewichtsrechnerEinfachProvider extends ChangeNotifier{
num _gewicht = 0;
num get gewicht => _gewicht;
void setGewicht(num newGewicht){
_gewicht = newGewicht;
notifyListeners();
}
}
as you see _gewicht is private and you can use it alive entire your project.
step 4) you should add the provider to main.dart:
MultiProvider(
providers: [
// you are adding your provider
ListenableProvider.value(value: GewichtsrechnerEinfachProvider()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: ...........
),
);
step 5) now you should use its setter and getter of gewicht:
as you see in _GewichtsrechnerEinfachState you are setting the value and should do this by using Consumer:
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
child: Consumer<GewichtsrechnerEinfachProvider>(//note this
builder: (context, gewichtsrechnerEinfachProvider ,child) {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//{two textinput fields setting the variables koerperlaenge and brustumfang are here}
Center(
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
decoration: ThemeHelper().buttonBoxDecoration(context),
child: ElevatedButton(
style: ThemeHelper().buttonStyle(),
child: Padding(
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Text(
"berechnen".toUpperCase(),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
onPressed: () async {
if (_formKey.currentState!.validate()) {
// and note this
gewichtsrechnerEinfachProvider.setGewicht(
Gewichtskalkulator().einfach(
brustumfang.toDouble(),
koerperlaenge.toDouble())
);
}
}),
),
),
],
),
);
}
),
),
);
}
step 6) now you should use its getter where ever you want:
List<Widget> buildEditingActions() => [
Consumer<GewichtsrechnerEinfachProvider>(
builder: (context, gewichtsrechnerEinfachProvider ,child) {
return ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: fumigruen_accent,
elevation: 0,
foregroundColor: Colors.black,
),
onPressed: () {
// Navigator.of(context).pop(gewicht);
print('here is your result:
${gewichtsrechnerEinfachProvider.gewicht}');
},
icon: Icon(Icons.save),
label: Text("Speichern"));
}
)
];
note that you can use your provider where ever you want even with this code not just consumer:
var gewichtsrechnerEinfachProvider = Provider.of<GewichtsrechnerEinfachProvider>(context,listen: false);
as you see by changing its value the provider notifies to where you are showing it.
Ich hoffe, ich konnte dir helfen ;)
happy coding my friend...
currently i am implementing a app where I am trying to get specific value from realtime firebase storage comparing with the current date and time or I mean, I want to get data that matches today's date and time. Please do help me on it.
For an example :
You can see in the screenshot the realtime fireabase data. i want to get data that matches the current date or specified date.
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class ReadPromise extends StatefulWidget {
#override
_ReadPromiseState createState() => _ReadPromiseState();
}
class _ReadPromiseState extends State<ReadPromise> {
Query _ref;
DatabaseReference reference =
FirebaseDatabase.instance.reference().child('Daily Verse');
final DateTime now = DateTime.now();
final DateFormat formatter = DateFormat("dd MMMM yyyy");
#override
void initState() {
// TODO: implement initState
super.initState();
String today = formatter.format(now);
_ref = FirebaseDatabase.instance
.reference()
.child('Daily Verse')
.orderByChild('date');
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.indigo[900],
title: Text('Daily Promise Archive', textAlign: TextAlign.center,),
),
body:Container(
height: double.infinity,
child: FirebaseAnimatedList(
query: _ref,
itemBuilder: (BuildContext context, DataSnapshot snapshot,
Animation<double> animation, int index) {
Map readVerse = snapshot.value;
readVerse['key'] = snapshot.key;
return _buildContactItem(readPromise: readVerse);
})
)
);
}
}
Widget _buildContactItem({readPromise}) {
return Container(
margin: EdgeInsets.symmetric(vertical: 10),
padding: EdgeInsets.all(10),
height: 130,
color: Colors.white,
child: Container(
child: Card(
color: Colors.indigo,
shadowColor: Colors.black,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
SizedBox(
width: 6,
),
Text(
readPromise['data'],
style: TextStyle(
fontSize: 16,
color: Colors.white,
fontWeight: FontWeight.bold),
),
],
),
SizedBox(
height: 20,
),
Row(
children: [
SizedBox(
width: 6,
),
Text(
readPromise['verse'],
style: TextStyle(
fontSize: 16,
color: Colors.white,
fontWeight: FontWeight.bold),
),
SizedBox(
width: 140,
),
Text(
readPromise['date'],
style: TextStyle(
fontSize: 16,
color: Colors.white,
fontWeight: FontWeight.bold),
),
],
)
]
)
)));
}
You're almost there:
_ref = FirebaseDatabase.instance
.reference()
.child('Daily Verse')
.orderByChild('date')
.equalTo(formatter.format(now));
I am calling API data inside Listview. builder in flutter but the error I am facing is the items are changing their positions automatically.
For Example, When I load this class for the First Time the arrangement of List items is the same as required but after 30-40 seconds the List items arrangement automatically starts changing, and data showing itself randomly.
I am looking for someone who can help me to fix this issue?
For this purpose here is myClass Code.
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart'as HTTP;
import 'package:worldcup/utils/colors.dart';
class SeriesSchedulePage extends StatefulWidget {
#override
_SeriesSchedulePageState createState() => _SeriesSchedulePageState();
}
class _SeriesSchedulePageState extends State<SeriesSchedulePage> {
List<dynamic> matches = [];
var match;
getSchedule() async {
http.Response response = await http
.get(Uri.parse("https://api.cricket.com.au/matches/2780"));
final Map parseData = await json.decode(response.body.toString());
matches = parseData['matchList']["matches"];
setState(() {
match = matches;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.primaryWhite,
appBar: AppBar(
backgroundColor: AppColors.yellow,
elevation: 0,
centerTitle: true,
leading: IconButton(
onPressed: () {
Navigator.pop(context,true);
},
icon: Icon(
Icons.arrow_back,
color: Colors.white,
),
),
title: Text(
'Schedule',
textScaleFactor: 0.9,
style: GoogleFonts.openSans(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 17),
),
),
body: Container(
child: FutureBuilder(
future: getSchedule(),
builder: (context, snapshot) {
if (match == null) {
return Center(
child: CupertinoActivityIndicator(
animating: true, radius: 15));
} else
return ListView.builder(
itemCount: matches.length,
shrinkWrap: true,
reverse: false,
itemBuilder: (context, index) {
if (matches[index]["status"] =="UPCOMING") {
return Card(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
child: Container(
width: double.infinity,
child: Padding(
padding: EdgeInsets.only(left: 15, top: 7, bottom: 7, right: 15),
child: Row(
children: [
SizedBox(width: 20,),
Expanded(
flex: 2,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
matches[index]['name'].toString(),
textScaleFactor: 0.9,
style: GoogleFonts.openSans(
fontWeight: FontWeight.w700, fontSize: 15),
),
SizedBox(height: 10,),
Text(
matches[index]["homeTeam"]['name'].toString(),
textScaleFactor: 0.9,
style: GoogleFonts.openSans(
fontWeight: FontWeight.w700, fontSize: 15),
),
SizedBox(height: 10,),
Text(
matches[index]["awayTeam"]['name'].toString(),
textScaleFactor: 0.9,
style: GoogleFonts.openSans(
fontWeight: FontWeight.w500, fontSize: 13),
),
],
),
],
),
),
],
),
),
)
);
} else {
return Center(
child: Text("No Upcoming Match in this series"),
);
}
}
);
},
),
)
);
}
}
The issue is because getSchedule() has a setState inside it. When the build method is called, getSchedule() will trigger, and since it is calling setState , the build method is being called again, causing your widgets to continuously rebuild in an infinite loop.
What you need to do is prevent such a loop from happening. I see that you are using FutureBuilder too, that is a solution but your implementation is incorrect.
What you should do is this:
Future<List<dynamic>> getSchedule() async {
http.Response response =
await http.get(Uri.parse("https://api.cricket.com.au/matches/2780"));
final Map parseData = await json.decode(response.body.toString());
var matches = parseData['matchList']["matches"];
return matches;
}
This function returns a Future<List<dynamic>> which your future builder can use to handle the builds. For info on future builder here https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html.
Since you FutureBuilder will react to what is provided by getSchedule() when the future is complete, you do not need to use setState to rebuild.
I have modified your SeriesShedualPage here is the full code:
class SeriesSchedulePage extends StatefulWidget {
#override
_SeriesSchedulePageState createState() => _SeriesSchedulePageState();
}
class _SeriesSchedulePageState extends State<SeriesSchedulePage> {
Future<List<dynamic>> getSchedule() async {
http.Response response =
await http.get(Uri.parse("https://api.cricket.com.au/matches/2780"));
final Map parseData = await json.decode(response.body.toString());
var matches = parseData['matchList']["matches"];
return matches;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: FutureBuilder<List<dynamic>>(
future: getSchedule(),
builder: (context, snapshot) {
if (snapshot.hasData) {
List<dynamic> matches = snapshot.data!;
return ListView.builder(
itemCount: matches.length,
shrinkWrap: true,
reverse: false,
itemBuilder: (context, index) {
if (matches[index]["status"] == "UPCOMING") {
return Card(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
child: Container(
width: double.infinity,
child: Padding(
padding: EdgeInsets.only(
left: 15, top: 7, bottom: 7, right: 15),
child: Row(
children: [
SizedBox(
width: 20,
),
Expanded(
flex: 2,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
matches[index]['name'].toString(),
textScaleFactor: 0.9,
),
SizedBox(
height: 10,
),
Text(
matches[index]["homeTeam"]['name']
.toString(),
textScaleFactor: 0.9,
),
SizedBox(
height: 10,
),
Text(
matches[index]["awayTeam"]['name']
.toString(),
textScaleFactor: 0.9,
),
],
),
],
),
),
],
),
),
));
} else {
return Center(
child: Text("No Upcoming Match in this series"),
);
}
});
}
return Center(
child: CupertinoActivityIndicator(animating: true, radius: 15));
},
),
));
}
}
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