Flutter future builder to list - flutter

I have some troubles in understanding how future builder works in flutter. I want to pass a list of String from my future call and I want to display them in a SingleChildScrollView.
The problem is that when I access the snapshot.data I can not access the element of the list. Because in my SingleChildScrollView I have container and in each container I want to display one String from the list.
This is the Future getData method with which I retrieve the data.
Future<List<String>> getData () async {
List<String> data = [];
data.add("A");
data.add("B");
data.add("C");
// DEBUG
await Future.delayed(const Duration(seconds: 2), (){});
return data;
}
And this is my future builder in which I want to display the data in each container. In the loading I added a shimmer effect.
FutureBuilder(
builder: (context, snapshot) {
List<Widget> children;
if (snapshot.hasData) {
children = <Widget>[
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
],
),
),
];
} else if (snapshot.hasError) {
children = <Widget>[
const Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'),
)
];
} else {
children = <Widget>[
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Shimmer.fromColors(
baseColor: Colors.grey.shade200,
highlightColor: Colors.grey.shade300,
child: Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
),
Shimmer.fromColors(
baseColor: Colors.grey.shade200,
highlightColor: Colors.grey.shade300,
child: Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
),
Shimmer.fromColors(
baseColor: Colors.grey.shade200,
highlightColor: Colors.grey.shade300,
child: Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
),
],
),
),
];
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: children,
),
);
},
future: getData(),
),
So in this way I can I access the elements of my list of Strings?

As #piskink mentioned, using ListView.builder is more efficient.
body: FutureBuilder<List<String>?>(
future: getData(),
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Text(snapshot.data?[index] ?? "got null");
},
);
}
/// handles others as you did on question
else {
return CircularProgressIndicator();
}
},
If you still wish to use SingleChildScrollView, you can generate items like
return Column(
children: List.generate(
snapshot.data!.length,
(index) => Text(snapshot.data?[index] ?? "got null"),
),
);
Check more about async-await and Future.

When you declare a FutureBuilder you have also to pass it it's data type. In this case it will be:
FutureBuilder<List<String>>(
future: getData(),
builder: (context,snapshot){
return ...;
}
)
If you don't declare its datatype, your snapshot will be considered as an AsyncDataSnapshot<dynamic> instead of AsyncDataSnapshot<List<String>>.

This is a full example for FutureBuilder with Null Safty
if you got these errors:
( The getter 'length' isn't defined for the type 'Object'. )
( The operator '[]' isn't defined for the type 'Object'. )
This is the Fix ↓↓↓↓↓
Fix & Important Note:
You have to select datatype of the Future Data that will be received.
Right: FutureBuilder<List>()
Wrong: FutureBuilder()
Full Simple Example:
import 'package:flutter/material.dart';
class FutureExample extends StatelessWidget {
const FutureExample({Key? key}) : super(key: key);
Future<List<String>> getData() async{
await Future.delayed(
const Duration(seconds:2)
);
return ["I'm Ramy","I'm Yasser", "I'm Ahmed", "I'm Yossif",];
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<List<String>>(
future: getData(),
builder: (context, snapshot) {
return snapshot.connectionState == ConnectionState.waiting
? const CircularProgressIndicator()
: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: List.generate(snapshot.data!.length,
(index) {
return Text(snapshot.data?[index] ?? "null") ;
},
),
);
},
),
),
);
}
}

Related

on other Page CustomListTile usage

I am trying to use CustomListTile Widget for format my JSON file on other Page.
This structure uses Future Builder and I can't see any error
child: FutureBuilder<Articles>(
future: _futureArticles,
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {
final articles = snapshot.data?.data;
return ListView.builder(
itemCount: articles!.length,
itemBuilder: (BuildContext context, int index) =>
customListTile(articles[index], context),
);
} else if (snapshot.hasError) {
return NewsError(
errorMessage: '${snapshot.hasError}',
);
} else {
return const NewsLoading(
text: 'Loading...',
);
}
},
),
on the other Page I have a CustomListTile Widget. I have imported the FutureBuilder page already
Widget customListTile(index article, BuildContext context) {
return InkWell(
onTap: () {
Icons.message;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => article(
index: article,
)));
},
child: Container(
margin: EdgeInsets.all(12.0),
padding: EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.0),
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 3.0,
),
]),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 200.0,
width: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(article[index].imageUrl!),
fit: BoxFit.cover),
borderRadius: BorderRadius.circular(12.0),
),
),
SizedBox(
height: 8.0,
),
Container(
padding: EdgeInsets.all(6.0),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(30.0),
),
child: Text(
article.category.name,
style: TextStyle(
color: Colors.white,
),
),
),
SizedBox(
height: 8.0,
),
Text(
article.title,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16.0,
),
)
],
),
),
);
}
but VS Code highlight index and this is not working
Widget customListTile(index article, BuildContext context) {
Where I am doing a mistake?
I guess index(index article) is no type. As far as I can see you need the index for Lists, to tell the app which "item" of the list it should take. If you want to retrieve an item of a list, you have to call the name of the list and then in []"the number" of the place, where the item is in the list. The type of "number" you need is of type int. So your argument index, should be of type int.
Try this:
Widget customListTile(int index, BuildContext context) {

type 'Future<List<dynamic>>' is not a subtype of type 'Future<List<FoodModel>>'

So I'm trying to get my foodmodel data to show up on my screen, I don't know what is wrong with this code, it must be something about await async but I can't figure it out. It only says type Future<List<dynamic>> is not a subtype of type Future<List<FoodModel>>. I'm still new to flutter. Is there anyway to get data using async await from this code?
class FoodPage extends StatefulWidget {
#override
_FoodPageState createState() => _FoodPageState();
}
class _FoodPageState extends State<FoodPage> {
Future<List<FoodModel>> foods;
#override
initState() {
super.initState();
setState(() {
var db= DatabaseHelperFood();
foods=db.getFoods();
});
}
GridView food_data (List<FoodModel> foods)
{
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemCount: foods.length,
itemBuilder: (_, int position)
{
return Card(
child:Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(FoodModel.map(foods[position]).alamat),
fit: BoxFit.cover,
)),
child: Container(
margin: EdgeInsets.fromLTRB(
0, 152, 0, 0),
child: Column(
children: <Widget>[
Container(
width: 500,
height: 25,
child: RaisedButton(
onPressed: () {
},
child: Text('Beli : $FoodModel.map(_foods[position]).harga',
textAlign: TextAlign
.center,
style: TextStyle(
color: Colors.white)),
color: Colors.black,
))
],
)
)
),);
},
);
}
foodlist(){
return Expanded(
child:FutureBuilder(
future:foods,
builder:(context,datas)
{
if(datas.hasData)
{
return food_data(datas.data);
}
else if(null== datas.data || datas.data.length==0)
{
return Text("No data");
}
return CircularProgressIndicator();
}
)
);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey[900],
leading: Icon(Icons.menu),
actions: <Widget>[
Padding(
padding: EdgeInsets.all(5),
child: Row(children: <Widget>[
Container(
child:Text("GoFlix",style:TextStyle(fontSize: 30)),
margin:EdgeInsets.only(right:90),
),
Container(
child: Icon(Icons.shopping_cart, size: 30),
margin: EdgeInsets.only(top: 5)),
Container(
margin: EdgeInsets.only(top: 5),
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.redAccent[800],
borderRadius: BorderRadius.circular(10)),
child: Center(child: Text("0")),
)
]))
]),
body:Container(
color:Colors.grey[800],
child: Column(
children: <Widget>[
Image.asset('Asset/Movieabanner.jpg'),
foodlist(),
])
)
);
}
}
If your Future value is List<FoodModel> you need to build your FutureBuilder as follows:
FutureBuilder<List<FoodModel>>(
future: foods,
builder: (context, datas) {
}
)
Since FutureBuilder handles async await things, instead of calling db.getFoods() inside your initState method, you can do it inside FutureBuilder as follows:
FutureBuilder<List<FoodModel>>(
future: db.getFoods(),
builder: (context, datas) {
}
)
But you are using foods in some other places, so you might need a little more refactoring.

Flutter: Creating GridView From Firebase Realtime DB items

Currently, in my app's homescreen I have a firebase_animated_list widget which creates a listView. However, I want to show these items in a GridView because it'll look much better.
Here's my code snippet.👇🏼
body: Column(
children: <Widget>[
Flexible(
child: FirebaseAnimatedList(
query: firebaseRef,
itemBuilder: (BuildContext context, DataSnapshot snapshot,
Animation<double> animation, int index) {
return InkWell(
child: ListTile(
contentPadding: EdgeInsets.all(7),
title: Text(mynode[index].key),
leading: CircleAvatar(
radius: 30,
child: FittedBox(
child: Text(mynode[index].id),
),
),
trailing: Icon(Icons.play_arrow),
onTap: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => DemoDb(
id: othernode[index].id,
),
),
),
),
);
},
),
),
],
),
This perfectly creates a list of items but how should I change it to a GridView? I tried using GridView.count in place of ListTile widget. but because it was nested inside the firebase_animated_list , Each grid is layed out inside this animated list.
Is there any plugins or libraries that can help me in this? perhaps a code snippet Or if someone can suggest me any better approach to achieve this, it would mean world to me.
Thank You.
try Using StreamBuilder to load the items in a map and then use a Gridview and then you can populate the Gridview with your data.
have a look at the following Example:
Here we have a model of the data that we're trying to pull from firebase.
class Product {
String key;
String cardid;
String cardname;
String cardimage;
int cardprice;
String carddiscription;
Product(this.key,this.cardid,this.cardname,this.cardimage,this.cardprice,this.carddiscription);
}
and here is how to implement a GridView inside a StreamBuilder and populate it with the data:
return StreamBuilder(
stream: FirebaseDatabase.instance
.reference()
.child("Products")
.onValue,
builder: (BuildContext context, AsyncSnapshot<Event> snapshot) {
if (snapshot.hasData) {
Map<dynamic, dynamic> map = snapshot.data.snapshot.value;
products.clear();
map.forEach((dynamic, v) =>
products.add( new Product(v["key"],v["cardid"] , v["cardname"],v["cardimage"] ,v["cardprice"], v["carddiscription"]))
);
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemCount: products.length,
padding: EdgeInsets.all(2.0),
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: (){
},
child: Padding(
padding: EdgeInsets.all(5),
child: Container(
width: (screenWidth(context)/2)-15,
height: 150,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(15.0)),
image: DecorationImage(
image: NetworkImage(products[index].cardimage),
fit: BoxFit.cover,
),
),
child: Padding(
padding: EdgeInsets.all(0),
child: Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(15.0)),
gradient: new LinearGradient(
colors: [
Colors.black,
const Color(0x19000000),
],
begin: const FractionalOffset(0.0, 1.0),
end: const FractionalOffset(0.0, 0.0),
stops: [0.0, 1.0],
tileMode: TileMode.clamp),
),
child: Padding(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
products[index].cardname,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500,color: Colors.white),
),
Text('Rs. ${products[index].cardprice}'
,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w200,color: Colors.white),
),
],
),
),
),
), /* add child content here */
),
),
);
},
);
} else {
return CircularProgressIndicator();
}
}),

How to get all documents that are inside of a collection that is inside of another collection on Firestore?

Well, I'm trying to build a function that when I click in a favorite icon I am choosing a place as one of my favorite places. And if I want to see my favorite places, I need just go to the favorite page that should return all my favorite places. I have two favorite places stored on my firestore. When I'm trying to get them, returns nothing... And that's the problem.
Each favorite document, contains fields like city, image etc. Here's my database: https://i.imgur.com/CmTr4vG.png
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class Favorites extends StatefulWidget {
#override
_FavoritesState createState() => _FavoritesState();
}
class _FavoritesState extends State<Favorites> {
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
dynamic loadFavorites() async{
final FirebaseUser user = await FirebaseAuth.instance.currentUser();
final dynamic userUid = user.uid;
return userUid;
}
dynamic document = loadFavorites();
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 30.0, bottom: 5.0),
child: Text("Favoritos",
style: TextStyle(fontSize: 20),
textAlign: TextAlign.center,
),
),
Container(
child: FutureBuilder<QuerySnapshot>(
future: Firestore.instance.collection("users").document(document.toString()).collection("favorites").getDocuments(),
builder: (context, snapshot){
if(!snapshot.hasData){
return Center(child: CircularProgressIndicator());
}else{
return snapshot.data.documents.isEmpty ? Center(child: Text("Nenhum favorito escolhido.")) : ListView.builder(
physics: const NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index){
return Container(
padding: EdgeInsets.all(10.0),
child: buildFavorite(width, height, snapshot.data.documents[index]),
);
},
);
}
},
),
),
],
),
),
);
}
Widget buildFavorite(double width, double height, DocumentSnapshot document){
return Container(
padding: EdgeInsets.all(10.0),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey,
offset: Offset(1.0, 1.0),
blurRadius: 10.0,
),
],
borderRadius: BorderRadius.circular(10.0),
),
child: Stack(
children: <Widget>[
//Padding(padding: EdgeInsets.only(top: 100),),
Container(
margin: EdgeInsets.only(bottom: 20.0, left: 20.0),
child: Text(document["title"], style: TextStyle(fontSize: 18),),
),
Container(
width: width * 0.37,
height: height * 0.18,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
image: DecorationImage(
fit: BoxFit.fill,
image: NetworkImage(document["image"]),
),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey,
offset: Offset(1.0, 1.0),
blurRadius: 1.0,
),
],
),
margin: EdgeInsets.only(left: width * 0.60),
),
Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 30.0),
child: Icon(Icons.location_on, color: Colors.red,),
),
Container(
margin: EdgeInsets.only(left: 10.0, top: 30.0),
child: Text(document["text"]),
),
],
),
Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 60.0),
child: Icon(Icons.phone, color: Colors.red),
),
Container(
margin: EdgeInsets.only(left: 10.0, top: 60.0),
child: Text(document["phone"]),
),
],
),
Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 90.0),
child: Icon(Icons.timer, color: Colors.red,),
),
Container(
margin: EdgeInsets.only(left: 10.0, top: 90.0),
child: Text(document["time"]),
),
],
),
],
),
);
}
}
Your Problem lies here:
future: Firestore.instance.collection("users").document(document.toString()).collection("favorites").getDocuments(),
document.toString() will return Instance of Future<dynamic> since the actual type of this variable is the return type of your loadUser() function which is Future<dynamic> and the toString() method of objects is usually Instance of CLASS_NAME. Generally I strongly recommend you to make use of the type safety of dart by always using explicit types instead of dynamic! Errors occuring while using types indicate that something you are trying is not correct and better helps to understand what kind of value is to be expected.
You are trying to retrieve the userUid to use it inside your FutureBuilder but unfortunately this function needs to be async since you have to get it from Firebase. The surrounding function (build of your Widget) is not async. Therefore you can't resolve the loadUser() function as you intend to. To fix this issue you need to extract the userUid and favorites retrieval outside your build function - let me show you an example:
Future<QuerySnapshot> getFavoritesFromUser() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
final String userUid = user.uid;
return Firestore.instance.collection("users").document(userUid).collection("favorites").getDocuments();
}
#override
Widget build(BuildContext context) {
...
Container(
child: FutureBuilder<QuerySnapshot>(
future: this.getFavoritesFromUser()
...

I want to add a new element after my horizontal listview how can I add it

This is the projected picture that shows how I am able to add an element.
Below is my code in which I want to add an element so that if my list is not present it also shows the element and if it present then the element is the last element.
I have tried this in some different ways.
Can anyone please help me?
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'alllist.dart';
List<Alllist> _alllist = [];
List<Alllist> get alllist => _alllist;
class EduCategory extends StatefulWidget{
final String listcategory;
final int intp;
EduCategory({this.listcategory,this.intp});
#override
EduCategoryState createState() {
return new EduCategoryState();
}
}
class EduCategoryState extends State<EduCategory> {
#override
Widget build(BuildContext context) {
// TODO: implement build
return Container(child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
widget.listcategory,
style: TextStyle(fontWeight: FontWeight.bold),
),
new Row(
children: <Widget>[
new Icon(Icons.play_arrow),
new Text("Watch All", style: TextStyle(fontWeight: FontWeight.bold))
],
)
],
),
Expanded(
child: new Padding(
padding: const EdgeInsets.only(top: 8.0),
child:new StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('all list').where("listcategory",isEqualTo: widget.listcategory).snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return new Text("no");
if (snapshot.data.documents.length == 0) return InkWell(
child: Stack(
children: <Widget>[
new Container(
width: 80.0,
height: 80.0,
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
border: Border.all(color: Colors.blueGrey),
borderRadius: BorderRadius.circular(5.0),
image: new DecorationImage(
fit: BoxFit.fill,
image: new AssetImage("assets/Plus.png")),
),
margin: const EdgeInsets.symmetric(horizontal: 20.0),
// child: Text(name),
),
Padding(padding: EdgeInsets.only(top: 80.0,left: 20.0),
child: Text("Add Lession",style: TextStyle(fontWeight: FontWeight.bold,color: Colors.blueGrey),),
),
],
),
onTap: (){},
);
return new ListView(
scrollDirection: Axis.horizontal,
children: buildGrid(snapshot.data.documents)
);;
}
),
))
],
),
);
}
List<Widget> buildGrid(List<DocumentSnapshot> documents) {
List<Widget> _gridItems = [];
_alllist.clear();
for (DocumentSnapshot document in documents) {
_alllist.add(Alllist.fromDocument(document));
}
for (Alllist alllist in _alllist) {
_gridItems.add(buildGridItem(alllist));
}
return _gridItems;
}
Widget buildGridItem(Alllist alllist,) {
return widget.intp==0?
InkWell(
child: Stack(
children: <Widget>[
new Container(
width: 80.0,
height: 80.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.blue,width: 4.0,style: BorderStyle.solid),
image: new DecorationImage(
fit: BoxFit.fill,
image: new NetworkImage(
alllist.imageUrl)),
),
margin: const EdgeInsets.symmetric(horizontal: 20.0),
// child: Text(name),
),
Padding(padding: EdgeInsets.only(top: 80.0,left: 10.0),
child: Text(alllist.title,style: TextStyle(fontWeight: FontWeight.bold,color: Colors.blueGrey),),
),
],
),
onTap: (){},
):new Row(
children: <Widget>[
InkWell(
child: Stack(
children: <Widget>[
new Container(
width: 80.0,
height: 80.0,
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(5.0),
image: new DecorationImage(
fit: BoxFit.fill,
image: new NetworkImage(
alllist.imageUrl)),
),
margin: const EdgeInsets.symmetric(horizontal: 20.0),
// child: Text(name),
),
Padding(padding: EdgeInsets.only(top: 80.0,left: 10.0),
child: Text(alllist.title,style: TextStyle(fontWeight: FontWeight.bold,color: Colors.blueGrey),),
),
],
),
onTap: (){},
)
]
);
}
}
You can use the ListView.builder with itemCount as snapshot.data.documents.length + 1.
Code sample:
new StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('all list').where("listcategory",isEqualTo: widget.listcategory).snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return new Text("no");
var documentsLength = snapshot.data.documents.length;
ListView.builder(itemCount: documentsLength + 1, // +1 for last element
itemBuilder: (context, index) {
if (index == documentsLength) {
//last view which have plus button
} else {
return buildGridItem((Alllist.fromDocument(snapshot.data.documents[index]))
}
});
})
I think that you have to just add condition in itemBuilder checkout in below code;
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final List<int> items=[1,2,3,4,5,6];
#override
Widget build(BuildContext context) {
final title = 'Mixed List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Container(
height: 100.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: items.length + 1 ,
itemBuilder: (context, index) {
if(index < items.length )
{ return Container(
color: Colors.blue,
width: 100.0,
padding: EdgeInsets.all(8.0),
child: new Center(
child: new Text(index.toString()),
),
);
}
else {
return new Container(
color: Colors.blue,
width: 100.0,
child: new Center(
child: new Text(index.toString() + "differnt"),
),
);
}
},
),
),
),
);
}
}