The getter 'length' was called on null in flutter - flutter

I have added three streamBuilder on my homepage and all the StreamBuilders fetch different data from cloud firestore but i am getting 'The getter 'length' was called on null in flutter' . I have tried to look for a solution on the internet but all in vain. Am getting this error:
════════ Exception caught by widgets library ═══════════════════════════════════
The getter 'length' was called on null.
Receiver: null
Tried calling: length
The relevant error-causing widget was
StreamBuilder<List<Order>>
lib/…/home/home.dart:52
Here is my home.dart:
import 'package:flutter/material.dart';
import 'package:merza/models/orders.dart';
import 'package:merza/models/user.dart';
import 'package:merza/screens/home/items.dart';
import 'package:merza/screens/home/orders/delivered_order.dart';
import 'package:merza/screens/home/orders/order_status.dart';
import 'package:merza/screens/user/add_order.dart';
import 'package:merza/services/auth.dart';
import 'package:merza/services/databse.dart';
import 'package:merza/shared/grid.dart';
import 'package:intl/intl.dart';
import 'package:merza/shared/menus.dart';
import 'package:merza/shared/splash_screen.dart';
import 'package:provider/provider.dart';
import 'package:merza/screens/home/orders/orders_list.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'orders/orders_tile.dart';
class Home extends StatelessWidget {
//Auth
AuthService _auth = AuthService();
//Database
Database _db = Database();
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
if(user.uid == null){
Navigator.pushNamedAndRemoveUntil(context, "/home", (r) => false);
}else{
return StreamBuilder<UserData>(
stream: Database(uid: user.uid).userData,
builder: (context, snapshot) {
if (snapshot.hasData) {
UserData userData = snapshot.data;
//Streambuilder for delivered orders
return StreamBuilder<List<Order>>(
stream: Database(receiver_nrc: userData.nrc, paramOne: 'payment_status', paramValue: 'unpaid').dataFetch,
builder: (context, snapshot2) {
String count_unpaid = snapshot2.data.length.toString();
if (snapshot2.hasData) {
return StreamBuilder <List<Order>>(
stream: Database(receiver_nrc: userData.nrc, paramOne: 'order_status', paramValue: 'delivered').dataFetch,
builder: (context, snapshot3) {
String count_awaiting = snapshot3.data.length.toString();
if (snapshot3.hasData) {
return StreamProvider<List<Order>>.value(
value: Database(receiver_nrc: userData.nrc).orders,
child: Scaffold(
appBar: LoggedBar(title: 'Merza',),
body: SingleChildScrollView(
child: Column(
children: [
Container(), // Required some widget in between to float AppBar
Container( // To take AppBar Size only
child: AppBar(
elevation: 0.0,
backgroundColor: Colors.white,
leading: IconButton(icon: Icon(Icons.home), color: Colors.green[900], onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => Home()));
},),
primary: false,
title: TextField(
decoration: InputDecoration(
hintText: "Search",
border: InputBorder.none,
hintStyle: TextStyle(color: Colors.green[900]))),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search, color: Colors.green[900]), onPressed: () {},),
],
),
),
Container(
color: Colors.green,
padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 20.0),
child: Text('A TRADING ZONE THAT PROMOTES SAFETY TRADING AND SECURE DIGITAL TRANSACTIONS', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: Colors.white)),
), Container(
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
width: 130,
child: ListTile(
title: Image.network('https://madvertadvertising.com/media/merza/images/seller.jpeg'),
onTap: (){
// Navigator.push(context, MaterialPageRoute(builder: (context) => ItemsPage()));
},
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const SizedBox(width: 8),
],
),
],
),
),
),
Expanded(
child: Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
width: 130,
child: ListTile(
title: Image.network('https://madvertadvertising.com/media/merza/images/delivery.jpeg'),
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => AwaitingOrdersList(nrc: userData.nrc, paramValueOne: 'order_status', paramValueTwo: 'delivered', barTitle: 'Delivered', isStaff: userData.is_staff.toString(), allowStaffPrivaledges: 'no',)));
},
),
),
const SizedBox(width: 8),
],
),
),
),
],
),
),
Container(
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
width: 130,
child: ListTile(
title: Image.network('https://madvertadvertising.com/media/merza/images/items.jpeg'),
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => ItemsPage()));
},
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const SizedBox(width: 8),
],
),
],
),
),
),
Expanded(
child: Container(
child: Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
width: 130,
child: ListTile(
title: Image.network('https://madvertadvertising.com/media/merza/images/payment.jpeg'),
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => DeliverdordersList(nrc: userData.nrc, paramValueOne: 'payment_status', paramValueTwo: 'paid', barTitle: 'Paid orders',)));
}
,
),
),
const SizedBox(width: 8),
],
),
),
),
),
],
),
),
Text('My recent placed orders', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)),
Container(
child: OrdersList(),
),
SizedBox(height: 10.0),
],
),
),
drawer: DrawerLogged()
),
);
}else{
return LoadingScreenCustom(page:'home');
}
}
);
}else{
return LoadingScreenCustom(page:'home');
}
}
);
}else{
return LoadingScreenCustom(page:'home');
}
}
);
}
}
}
I don't know if it is a good practice to add multiple stream builders on the same page.

Put String count_unpaid = snapshot2.data.length.toString(); line inside the if (snapshot2.hasData) block.
Put String count_awaiting = snapshot3.data.length.toString(); line inside the if (snapshot3.hasData) block.

Related

How do I change the position of the alert dialog in top in Flutter, Align TopCenter does not work

i'm new in Flutter. How do I change the position of the alert dialog in top of Screen in Flutter, I've used align TopCenter but it doesn't work. is there a solution?
this is my code:
body: Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
InkWell(
onTap: () {
ErrorAlert(context: context, message: "error message");
},
child: Container(
alignment: Alignment.center,
padding: EdgeInsets.only(top: appDimens.paddingw6),
child: Text(
"Show Dialog",
style: TextStyle(
color: Color(0xffFF9900),
),
),
),
),
],
),
),
);
This is ErrorAlert widget
Future<dynamic> ErrorAlert({
required BuildContext context,
String? message,
}) {
return showDialog(
context: context,
barrierColor: Colors.white.withOpacity(0),
barrierDismissible: false,
builder: (contex) {
return Align(
alignment: Alignment.topCenter,
child: AlertDialog(
backgroundColor: Color(0xffFFF4F2),
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
content: Container(
height: 20,
width: MediaQuery.of(context).size.width - 40,
child: Row(
// mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Image.asset(
"assets/icon/padlock.png",
height: 20,
),
Text(message ?? "Error",
style: TextStyle(color: Color(0xffFC6762))),
],
),
Center(
child: IconButton(
..........
),
),
],
),
),
),
);
});
}
this is the result:
Just remove AlertDialog from ErrorAlert function, dialog will be shown as you expected. As we know AlertDialog is a kind of Dialog. So we shouldn't use AlertDialog inside showDialog widget.
Future<dynamic> ErrorAlert({
required BuildContext context,
String? message,
}) {
return showDialog(
context: context,
barrierColor: Colors.white.withOpacity(0),
barrierDismissible: false,
builder: (contex) {
return Align(
alignment: Alignment.topCenter,
child: Material(
child: Container(
color: Color(0xffFFF4F2),
height: 20,
width: MediaQuery.of(context).size.width - 40,
child: Row(
// mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Icon(Icons.desktop_mac, color: Colors.blue,),
Text(message ?? "Error",
style: TextStyle(color: Color(0xffFC6762))),
],
),
Center(
child: IconButton(onPressed: () { }, icon: Icon(Icons.read_more),
),
),
],
),
),
),
);
});
}
You can use insetPadding of AlertDialog, like this:
AlertDialog(
insetPadding: EdgeInsets.only(bottom: 300),//<---- add this
backgroundColor: Color(0xffFFF4F2),
elevation: 0,
...
)
Or you can Wrap your AlertDialog with Column like this:
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
AlertDialog(
backgroundColor: Color(0xffFFF4F2),
elevation: 0,
...
)
]
)

Failing to get data from Firestore after Flutter Upgrades

I recently upgrade all the depencies. It required to change all my codes.
Now I face an issue to retrieve data from Firebase.
The main codes impacted are below.
BlocBuilder - cubit was replaced by bloc
BlocBuilder(
bloc: ordersBloc,
buildWhen: (previous, current) {
if (current is UpdateOrderAnalyticsState ||
current is GetOrderAnalyticsFailedState ||
current is GetOrderAnalyticsInProgressState) {
return true;
}
return false;
},
builder: (context, state) {
if (state is GetOrderAnalyticsInProgressState) {
return Shimmer.fromColors(
period: Duration(milliseconds: 800),
baseColor: Colors.grey.withOpacity(0.5),
highlightColor: CompanyColors.color[800].withOpacity(0.5),
child: ShimmerCommonMainPageSmallItem(size: size),
);
}
if (state is GetOrderAnalyticsFailedState) {
return Center(child: Text('FAILED'));
}
if (state is UpdateOrderAnalyticsState) {
orderAnalytics = state.orderAnalytics;
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Material(
child:
InkWell(
splashColor: CompanyColors.color[700].withOpacity(0.5),
onTap: () {
HapticFeedback.heavyImpact();
Navigator.push(
context,
MaterialPageRoute(builder: (context) => InventoryPage()),
);
},
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 1),
child: Container(
padding: const EdgeInsets.all(10.0),
decoration: _mainthembox,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
'GESTION INVENTAIRE',
overflow: TextOverflow.clip,
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
color: CompanyColors.color[50],
fontSize: 15,
fontWeight: FontWeight.w500,
),
),
SizedBox(
height: 5.0,
),
Container(
width: 55.0,
height: 55.0,
alignment: Alignment.center,
padding: const EdgeInsets.all(15.0),
decoration: _thembox,
child: Icon(
Icons.account_balance_outlined,
color: CompanyColors.color[50],
size: 25.0,
),
),
SizedBox(
height: 10.0,
),
],
),
),
),
),
),
),
),
CloudFirestore - documentSnapshot.data()['cancelledOrders'] was replaced by documentSnapshot.get('cancelledOrders')
class OrderAnalytics {
var cancelledOrders;
var cancelledSales;
var deliveredOrders;
var deliveredSales;
var newOrders;
var newSales;
var processedOrders;
var processedSales;
var totalOrders;
var totalSales;
OrderAnalytics({
this.cancelledOrders,
this.cancelledSales,
this.deliveredOrders,
this.deliveredSales,
this.newOrders,
this.newSales,
this.processedOrders,
this.processedSales,
this.totalOrders,
this.totalSales,
});
factory OrderAnalytics.fromFirestore(DocumentSnapshot documentSnapshot) {
return OrderAnalytics(
cancelledOrders: documentSnapshot.get('cancelledOrders'),
cancelledSales: documentSnapshot.get('cancelledSales'),
deliveredOrders: documentSnapshot.get('deliveredOrders'),
deliveredSales: documentSnapshot.get('deliveredSales'),
newOrders: documentSnapshot.get('newOrders'),
newSales: documentSnapshot.get('newSales'),
processedOrders: documentSnapshot.get('processedOrders'),
processedSales: documentSnapshot.get('processedSales'),
totalOrders: documentSnapshot.get('totalOrders'),
totalSales: documentSnapshot.get('totalSales'),
);
}
}
see below error messages

Images don't displayed on screen

I have modified my code. I thought I could achieve what I am willing to do but I am still having an issue. The first image is fine, but when I am adding more images, they don't display to the screen. The idea is to allow the user to click on a button to select one or several images. Then, he can tap on a second button and add one pfd file, it is like adding attachment in email.Then, if the user wants he can tap on the first button and add an other image. The list of all the documents should be displayed on the screen. I though that maybe a set State is missing somewhere. Here is the code. I do not understand where is my mistake. Thank you in advance.
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
List<PlatformFile>? _paths;
List<String> filesGB =[];
bool _loadingPath = false;
String fileExtension='';
String _fileName='';
// To access the pictures
void _openPictureFileExplorer() async {
setState(() => _loadingPath = true);
try {
_paths = (await FilePicker.platform.pickFiles(
type: FileType.media,
allowMultiple: true,
))?.files;
if (_paths != null) {
_paths!.forEach((element) {
filesGB.add(element.path.toString());
print(filesGB);
print(filesGB.length);
});
setState(() {
});
}
} on PlatformException catch (e) {
print("Unsupported operation" + e.toString());
} catch (ex) {
print('$ex');
}
if (!mounted) return;
setState(() {
_loadingPath = false;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: const Text('File Picker app'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 20.0),
//#############
//Display card with button to select type of document
child: Card(
child:
Container(
// color: Colors.red,
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//Attachement
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
Icon(Icons.attach_file),
Text('Attachment'),
],
)
),
onTap: () async {
fileExtension = 'pdf';
_openDocumentFileExplorer();
},
),
),
//Photo
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
Icon(Icons.add_a_photo_rounded),
Text('Photo'),
],
)
),
onTap: () {
fileExtension = 'jpeg';
_openPictureFileExplorer();
},
),
),
],
),
)),
),
Builder(
builder: (BuildContext context) => _loadingPath ?
Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child:const CircularProgressIndicator(),
)
: filesGB.isNotEmpty ?
Column(
children: listOfCards(filesGB),
)
:Text('Nothing to display'),
),
]),)))));
}
}
List<Widget> listOfCards(List<String> item){
List<Widget> list = <Widget>[];
ListView.builder(
itemCount: filesGB.length,
itemBuilder: (BuildContext ctxt, int index) {
return new Container(
height: 114,
child: GestureDetector(
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 10,
child: ClipPath(
clipper: ShapeBorderClipper(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 113, width: 113,
child: Image.file(File(item[i].toString()),
fit: BoxFit.fill,
width: double.infinity,),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(item[i]
.split('/')
.last),
),
),
],
),
),),
),
);
});
return list;
}
first of all, you don't need to use for loop for building your pictures list
just use ListView.builder
but about your problem, I think it happens because you set selected pictures in a row
then return that row as a child of your column
so your pictures align horizontally and column just show widgets in vertical aligns
in other words, your column just have one child, and its a Row
so column just show pictures as possible then you just see the first picture.
for solving this problem you should return a list of widgets in the listOfCards function
just do these simple changes and I hope your problem solved
change your function return parameter to List<Widget>
Widget listOfCards(List<String> item) {
to
List<Widget> listOfCards(List<String> item) {
then just return your list
return list;
and your column should look like this
Column(
children: listOfCards(filesGB),
)
I have find a working solution. It does what I was expecting with image. I still have a problem when I delete a record, the card is not removed. I do not find where I should use the setState. I will continue to investigate.
body: Center(
child: Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 20.0),
//#############
//Display card with button to select type of document
child: Card(
child:
Container(
// color: Colors.red,
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//Attachement
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
Icon(Icons.attach_file),
Text('Attachment'),
],
)
),
onTap: () async {
fileExtension = 'pdf';
_openDocumentFileExplorer();
},
),
),
//Photo
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
Icon(Icons.add_a_photo_rounded),
Text('Photo'),
],
)
),
onTap: () {
fileExtension = 'jpeg';
_openPictureFileExplorer();
},
),
),
],
),
)),
),
Builder(
builder: (BuildContext context) => _loadingPath ?
Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child:const CircularProgressIndicator(),
)
: filesGB.isNotEmpty ?
Column(
children: getList(),//[listOfCards(filesGB)],
)
:Text('Nothing to display'),
),
]),)))));
}
}
List<Widget> getList() {
List<Widget> childs = [];
for (var i = 0; i < filesGB.length; i++) {
childs.add(
GestureDetector(
onTap: (){
print ("Pressed");
},
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 10,
child: ClipPath(
clipper: ShapeBorderClipper(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 113,width: 113,
child: fileExtension == 'pdf'?
Image.asset('assets/logo_pdf.png',
// fit: BoxFit.fill,
// width: double.infinity,
):
Image.file(File(filesGB[i].toString()),
fit: BoxFit.fill,
width: double.infinity,),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(filesGB[i].toString().split('/').last,//_nameOfFile,//name,
style: TextStyle(fontWeight: FontWeight.bold),),
),
),
Padding(
padding: const EdgeInsets.only(right:25.0),
child: IconButton(onPressed: (){
//delete a record and the card displaying this record
// Delete the selected image
// This function is called when a trash icon is pressed
if (filesGB.length > 1) {
filesGB.removeAt(i);
print(filesGB);
setState(() {});
}
},
icon:Icon (Icons.delete, color: Colors.red,),),
)
],
),
),
//subtitle: Text(path),
),
));}
return childs;
}

This function has a return type of 'Row', but doesn't end with a return statement

i am trying to retrieve data from firestore as dropdown list, got this tutorial and error show up, please help, totally new with flutter.
This function has a return type of 'Row', but doesn't end with a return statement.
Try adding a return statement, or changing the return type to 'void'.
here is the code :
class _MyHomePageState extends State<MyHomePage> {
var selectedCurrency, selectedType;
final GlobalKey<FormState> _formKeyValue = new GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(
Icons.edit,
color: Colors.white,
),
onPressed: () {}),
title: Container(
alignment: Alignment.center,
child: Text("Account Details",
style: TextStyle(
color: Colors.white,
)),
),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.edit,
size: 20.0,
color: Colors.white,
),
onPressed: null,
),
],
),
body: Form(
key: _formKeyValue,
autovalidate: true,
child: new ListView(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
children: <Widget>[
SizedBox(height: 20.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.edit,
size: 25.0,
color: Color(0xff11b719),
),
SizedBox(width: 50.0),
],
),
SizedBox(height: 40.0),
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection("currency").snapshots(),
builder: (context, snapshot) {
}),
SizedBox(
height: 150.0,
),
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
RaisedButton(
color: Color(0xff11b719),
textColor: Colors.white,
child: Padding(
padding: EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text("Submit", style: TextStyle(fontSize: 24.0)),
],
)),
onPressed: () {},
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0))),
],
),
],
),
));
}
}
I'm totally new to Flutter myself, but it appears the method build of the MyHomePageState class does have a return statement. In fact, all the method body is wrapped inside that return statement:
Widget build(BuildContext context) {
return Scaffold(
...
)}
That build method returns a complete description of your page, including the Row you mentioned in your question deeply nested in structure:
return Scaffold(
...
body: Form(
...
child: new ListView(
...
children: <Widget>[
SizedBox(height: 20.0),
Row( <---------------- here it is
...
Or did I missed your point?

Flutter sort data Firestore with Streambuilder

My goal: When the user presses the "List" button inside "_mainListItem" I want the listview to get sorted by orderBy. Aswell as updated on screen
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class mainlist extends StatefulWidget {
#override
_mainlistpage createState() => _mainlistpage();
}
class _mainlistpage extends State<mainlist> {
Widget homePage() {
return StreamBuilder(
stream: Firestore.instance.collection("Test").snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return Text("Loading");
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
_mainListItem(context, snapshot.data.documents[index]));
},
);
}
Widget _mainListItem(BuildContext context, DocumentSnapshot document) {
return Card(
color: Colors.white,
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => profile(context, document)));
},
child: Container(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.black12))),
child: Row(
children: [
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
children: <Widget>[
Stack(
alignment: Alignment.topRight,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 5),
child: ClipRRect(
borderRadius:
BorderRadius.circular(0.0),
child: FittedBox(
child: Image.asset(
"assets/Profile Picture.png",
fit: BoxFit.fill,
)),
),
),
Padding(
padding: const EdgeInsets.only(
top: 7, right: 4),
child: Text(
'Test',
style: TextStyle(fontSize: 12),
),
),
]),
Row()
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
document['name'],
),
// Text("2km"),
],
),
],
),
],
),
),
],
),
),
Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 5, bottom: 5),
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 10, right: 7),
child: Container(
child: Material(
borderRadius: BorderRadius.circular(5),
shadowColor: Colors.black,
elevation: 1,
child: SizedBox(
height: 28,
width: 68,
child: IconButton(
padding: EdgeInsets.only(bottom: 10),
**icon: Icon(Icons.list),
disabledColor: Colors.blue,
iconSize: 25,**
)),
),
),
),
],
),
)
],
)
],
),
),
),
);
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return new Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
backgroundColor: Colors.grey,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
color: Colors.red,
),
title: Text("Test"),
centerTitle: true,
actions: <Widget>[
IconButton(
icon: Icon(Icons.menu),
iconSize: 30,
color: Colors.white,
)
],
),
body: homePage(),
);
}
}
I have tried
- adding the streambuilder function into the ontapped: on the List button
- have read and watched every video there is and still can't find the solution
note: the app looks weird because I deleted unnecessary information
You can sort the list items before the snapshot method like:
.orderBy('sortField', descending: true).snapshot()
I hope this works for you.
Try mapping the values to a List<CustomObject> and using the list of objects in your list view.
i suggest you use state to determine the field how your list will be sorted by.
this is what i'd do to achieve this (continuing from the same code):
...
class _mainlistpage extends State<mainlist> {
String _orderBy = 'defaultSort'; //? HERE YOU PUT WHAT YOUR SORTING FIELD NAME IS
bool _isDescending = true; //? THIS IS WHAT WILL SET THE ORDER SORTING
Widget homePage() {
return StreamBuilder(
stream: Firestore.instance
.collection("Test")
.orderBy(_orderBy, descending: _isDescending) //? PUT THE ORDERBY QUERY HERE
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return Text("Loading");
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
_mainListItem(context, snapshot.data.documents[index]));
},
);
}
...
somewhere in the class, put the button or dropdown and use setState(...) to set the
states of the new variables.
NOTE: you might have to create 'indexes' in firestore. you will get errors when a new
index is required.