single document in same collection Firestore Flutter - flutter

I build a quiz app and i use firestore for the data, i need a code for this : when the user select answer 1 he goes to page A , but when he select answer 2 he goes to page B ... etc
This is where am i : all the answers go to the same page when i tap on it, i want for every answer has his own page
This is my code :
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class question14 extends StatefulWidget {
#override
_question14State createState() => _question14State();
}
class _question14State extends State<question14> {
int selectedIndex
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder(
stream: Firestore.instance.collection('numberzz').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const Text('Loading ...');
return ListView.builder(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.fromLTRB(100.0, 0.0, 0.0, 0.0),
itemExtent: 200.0,
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
final DocumentSnapshot document =
snapshot.data.documents[index];
return Container(
padding: EdgeInsets.fromLTRB(0.0, 300.0, 0.0, 450.0),
child: ListTile(
contentPadding: selectedIndex == index
? EdgeInsets.all(0.0)
: EdgeInsets.all(25.0),
title: Image.network(
document['number'],
),
selected: selectedIndex == index,
onTap: () {
Firestore.instance.runTransaction((transaction) async {
DocumentSnapshot freshSnap =
await transaction.get(document.reference);
await transaction.update(freshSnap.reference, {
'vote': freshSnap['vote'] + 1,
});
});
Navigator.push(
context, MaterialPageRoute(
builder: (context) => new page()));
setState(() {
selectedIndex = index;
});
},
),
);
},
);
}));
}
}
thanks for your help !

You can check which index is selected before navigating. Kind of conditional navigation.
switch(selectedIndex){
case 0:
Navigator.of(context).push(.....(Page A));
break;
case 1:
.......
break;
I think you get the point.
But this code should come after
setState(() { selectedIndex = index };

Related

Get index of an Item from an other List

I started to use providers but I have a problem. I want to get the index of items that are in an other list in an other screen. How can i get themĀ ? I have two screens: a home screen and a favorite screen and I have a listView in each. I want to get the index of the item in the home screen when it is remove from the favorite screen. This is the link of my code on GitHub : https://github.com/Rianou20/my_app_from_scratch/tree/master/my_app_from_scratch. And some relevant parts of my code :
favModel.dart
class FavModel extends ChangeNotifier {
List<Item> favList = [];
List<bool> isInFav = [];
addInFavorite(title, description, index){
Item item = Item(title: title, description: description, );
favList.add(item);
isInFav[index] = true;
notifyListeners();
}
removeOfFavorite(int index, int index2){
favList.removeAt(index);
isInFav[index2] = false;
notifyListeners();
}
implement(){
isInFav.add(false);
}
}
favorite_screen.dart
class Favorite extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Favorite'),
),
body: Consumer<FavModel>(
builder: (context, favModel, child) {
return ListView.builder(
itemCount: favModel.favList.length,
itemBuilder: (context, index) {
return TextObject(favModel.favList[index].title,
favModel.favList[index].description),
Padding(
padding: const EdgeInsets.all(7.0),
child: GestureDetector(
child: Icon(
Icons.favorite,
color: Colors.red,
size: 32,
),
onTap: () {
favModel.removeOfFavorite(index, index);
}),
),
});
},
),
);
}
}
home_screen.dart
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
actions: [
IconButton(
icon: Icon(Icons.favorite_border),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
fullscreenDialog: true,
builder: (context) {
return Favorite();
},
),
),
),
],
),
body: Consumer<FavModel>(builder: (context, favModel, child) {
return ListView.builder(
shrinkWrap: false,
itemCount: itemData.length,
itemBuilder: (context, index) {
favModel.implement();
return TextObject(
itemData[index].title, itemData[index].description),
Padding(
padding: const EdgeInsets.all(7.0),
child: GestureDetector(
child: Icon(
favModel.isInFav.elementAt(index)
? Icons.favorite
: Icons.favorite_border,
color:
favModel.isInFav[index] ? Colors.red : null,
size: 32,
),
onTap: () {
favModel.isInFav[index]
? null
: Provider.of<FavModel>(context,
listen: false)
.addInFavorite(
itemData[index].title,
itemData[index].description,
index,
);
}),
);
});
}),
);
}
}
Where I want to get the index is in the favorite_screen.dart at this line favModel.removeOfFavorite(index, index);
Without knowing the exact use case, you can potentially store the removed values in a list and use them on your home screen.
class FavModel extends ChangeNotifier {
List<Item> favList = [];
List<bool> isInFav = [];
List<int> _removedItemIndexList = []
get removedItemIndexList => _removedItemIndexList;
addInFavorite(title, description, countdown, imageURL, index){
Item item = Item(title: title, description: description, countdown:countdown, imageURL: imageURL);
favList.add(item);
isInFav[index] = true;
notifyListeners();
}
removeOfFavorite(int index, int index2){
favList.removeAt(index);
isInFav[index2] = false;
_addToRemovedIndexList(index);
notifyListeners();
}
void _addToRemovedIndexList(int index) {
_removedItemIndexList.add(index);
}
implement(){
isInFav.add(false);
}
}
And then use on home_sreen.dart as
...
body: Consumer<FavModel>(builder: (context, favModel, child) {
List<int> removedIndexes = favModel.removedItemIndexList;
return ListView.builder( ... ) };
Note that the FavModel provider class must be lifted above then home_screen.dart on the widget tree in order to be able to access its values. i.e. you would want to do something like this in your main.dart
...
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(
value: FavModel(),
),
],
child: MaterialApp(...

Refresh swipe up to refresh widget flutter

I have an app that gets some data from firebase and than calls a class to display a widget based on the data from firebase. I tried adding a swipe up refresh but i have no idea where to put it and what to to call on refresh. I was trying it using the RefreshIndicator.
Here i will put my code in which it calls the database(firebase) and than creates an widget for each event in the database.
If you need any more information, please feel free to comment. Thank you so much for the help!
FutureBuilder(
future: databaseReference.once(),
builder: (context, AsyncSnapshot<DataSnapshot> snapshot) {
List lists = [];
if (snapshot.hasData) {
lists.clear();
Map<dynamic, dynamic> values = snapshot.data.value;
values.forEach((key, values) {
lists.add(values);
});
return new ListView.builder(
primary: false,
padding: EdgeInsets.only(left:12.0,right:12,bottom: 15,),
shrinkWrap: true,
itemCount: lists.length,
itemBuilder: (BuildContext context, int index) {
if(lists[index]["Status"]== "Active"){;
return Container(
child:EvendWidget(lists[index]["EventImage"],
Text(lists[index]["EventName"]).data,
Text(lists[index]["EventLocation"]+ ", "+lists[index]["EventCounty"] ).data,
Text(lists[index]["Date"]+ ", "+lists[index]["Time"]+ " - "+lists[index]["Time"]).data,
Text(lists[index]["Duration"]+ " H").data,
Text(lists[index]["Genre"]).data,
Text(lists[index]["Price"]).data,false));}else{return SizedBox.shrink(); };
});
}
return Container(
margin: const EdgeInsets.only(top: 300),
child:CircularProgressIndicator());
}),
Do something like this..
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
onRefresh: () async {
//write your code here to update the list*********
},
child: ListView.builder(
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return Text('Line $index');
}
)
),
);
}
}
You can try with below lines may be it will work for you
return RefreshIndicator(
color: Colors.blue,
onRefresh: () {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (_) => HomePage()));
},
child: ListView.builder(
....
));

How can i use a Future Int using a Provider?

I am trying to show a live count of total documents in an Appbar. I get the right information in my console, but when i try to pass it with an Provider it returns an Instance of 'Future'. Can someone tell why i am getting still an Instence even if i await the result and the result is printed correctly in my console?
this is where i get the Future int and print the result to my console.
class AuthenticationService extends ChangeNotifier {
Future<int> totalJumps(jumpDict) async {
var respectsQuery = _db.collection(jumpDict);
var querySnapshot = await respectsQuery.get();
var result = querySnapshot.docs.length;
print(result);
// notifyListeners();
return result;
}
}
This is were it should show the result as a int in the title of the appBar
class LazyListOnline extends StatefulWidget {
static const String id = 'Lazy_list_online';
#override
_LazyListOnlineState createState() => _LazyListOnlineState();
}
class _LazyListOnlineState extends State<LazyListOnline> {
#override
Widget build(BuildContext context) {
String userDict = Provider.of<AuthenticationService>(context).findJumpDict;
var _firestoreDb =
FirebaseFirestore.instance.collection(userDict).snapshots();
var totalJump = Provider.of<AuthenticationService>(context)
.totalJumps(userDict)
.toString();
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.popAndPushNamed(context, HomeDrawer.id);
}),
title: Text('totalJumps'),
body: Stack(children: [
Padding(
padding: const EdgeInsets.all(18.0),
child: Container(
decoration: BoxDecoration(),
),
StreamBuilder<QuerySnapshot>(
stream: _firestoreDb,
builder: (context, snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
return ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, int index) {
return JumpItem(
snapshot: snapshot.data,
index: index,
);
});
}),
]),
);
}
}
I think you just need to store only the amount of documents as an int in Provider like.
class DocumentData extends ChangeNotifier {
int documentLength;
void setCurrentLengthOfDocuments(int length) {
this. documentLength = length;
notifyListeners();
}
}
Then in StreamBuilder. Every time data has been changed. You just need to update. Regrading to your example be something like.
StreamBuilder<QuerySnapshot>(
stream: _firestoreDb,
builder: (context, snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
// Update amount of documents length
Provider.of<DocumentData>(context, listen: false)
.setCurrentLengthOfDocuments(lengthOfCurrentDocuments);
return ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, int index) {
return JumpItem(
snapshot: snapshot.data,
index: index,
);
});
}),
]),
Then when you can get the length of documents every where on this page by just use Consumer widget. Or get the value directly from Provider.

Flutter how to change the background color of a selected tile from a ListTile

I am trying to change the background of a selected tile from a ListTile.
I searched and found the following two posts, however non of them worked with my problem.
Post1
Post2
The better I got was with the help from #CopsOnRoad's answere.
With the following code, if I select multiple tiles, all remain select. How to select only one at the time and deselect the previous selected?
The tile index is limited by itemCount: is books.length.
List<Favorited> books;
// todo: this needs to be changed, has a hard coded value of 200
List<bool> _selected = List.generate(200, (i) => false); // Pre filled list
#override
Widget build(BuildContext context) {
final booksProvider = Provider.of<Model>(context);
return Container(
child: StreamBuilder(
stream: booksProvider.getUserFavList('103610812025'),
builder: (context, AsyncSnapshot<List<Favorited>> snapshot) {
if (snapshot.hasData) {
books= snapshot.data.toList();
return ListView.builder(
itemCount: books.length,
itemBuilder: (buildContext, index) {
return Container(
color: _selected[index] ? Colors.amber : Colors.transparent,
child: ListTile(
title: InkWell(
child: Text(snapshot.data[index].title),
onTap:() {
setState(() {
_selected[index] = !_selected[index];
});
}),
subtitle: Text(snapshot.data[index].name),
),
);
});
} else {
return Text('Fetching');
}
}),
);
Let a one variable to save selected tile index.
List<Favorited> books;
// todo: this needs to be changed, has a hard coded value of 200
List<bool> _selected = List.generate(200, (i) => false); // Pre filled list
int selectedIndex;
#override
Widget build(BuildContext context) {
final booksProvider = Provider.of<Model>(context);
return Container(
child: StreamBuilder(
stream: booksProvider.getUserFavList('103610812025'),
builder: (context, AsyncSnapshot<List<Favorited>> snapshot) {
if (snapshot.hasData) {
books= snapshot.data.toList();
return ListView.builder(
itemCount: books.length,
itemBuilder: (buildContext, index) {
return Container(
color: selectedIndex == index ? Colors.amber : Colors.transparent,
child: ListTile(
title: InkWell(
child: Text(snapshot.data[index].title),
onTap:() {
setState(() {
selectedIndex = index;
});
}),
subtitle: Text(snapshot.data[index].name),
),
);
});
} else {
return Text('Fetching');
}
}),
);

what is missing here ? Flutter - single selection

i'm creating a quiz app and i want to make some questions with single selection answer,
this is what it looks like for now :
Full code :
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class question14 extends StatefulWidget {
#override
_question14State createState() => _question14State();
}
class _question14State extends State<question14> {
final isSelected = [false, false, false];
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder(
stream: Firestore.instance
.collection('numberzz')
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const Text('Loading ...');
return ListView.builder(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.fromLTRB(100.0, 0.0, 0.0, 0.0),
itemExtent: 200.0,
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
final DocumentSnapshot document =
snapshot.data.documents[index];
return
Container(
padding: EdgeInsets.fromLTRB(0.0, 300.0, 0.0, 450.0),
child: ListTile(
contentPadding: isSelected[index]
? EdgeInsets.all(0.0)
: EdgeInsets.all(25.0),
title: Image.network(
document['number'],
),
selected: !isSelected[index],
onTap: () {
Firestore.instance.runTransaction((transaction) async {
DocumentSnapshot freshSnap =
await transaction.get(document.reference);
await transaction.update(freshSnap.reference, {
'vote': freshSnap['vote'] + 1,
});
});
setState(() {
isSelected[index] = !isSelected[index];
});
},
),
);
},
);
);
}
}
thanks you so much for your help !
Instead of using list of booleans, you can just store the selected index.
I used selectedIndex to have the answer's selection which is selected by the user at last.
Updated code:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class question14 extends StatefulWidget {
#override
_question14State createState() => _question14State();
}
class _question14State extends State<question14> {
int selectedIndex = 0;//for unselect, you can use null
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder(
stream: Firestore.instance.collection('numberzz').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const Text('Loading ...');
return ListView.builder(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.fromLTRB(100.0, 0.0, 0.0, 0.0),
itemExtent: 200.0,
itemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index) {
final DocumentSnapshot document =
snapshot.data.documents[index];
return Container(
padding: EdgeInsets.fromLTRB(0.0, 300.0, 0.0, 450.0),
child: ListTile(
contentPadding: selectedIndex == index
? EdgeInsets.all(0.0)
: EdgeInsets.all(25.0),
title: Image.network(
document['number'],
),
selected: selectedIndex == index,
onTap: () {
Firestore.instance.runTransaction((transaction) async {
DocumentSnapshot freshSnap =
await transaction.get(document.reference);
await transaction.update(freshSnap.reference, {
'vote': freshSnap['vote'] + 1,
});
});
setState(() {
selectedIndex = index;
});
},
),
);
},
);
}));
}
}