Related
I want to show data from my firebase cloudfirestore as you see in the picture:
In a Settings page I want to show all the information from the logged-in user.
Here is the Settings-Code ("einstellungen" in german):
class einstellungen extends StatelessWidget {
final user = FirebaseAuth.instance.currentUser;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text("Einstellungen"),
),
backgroundColor: Colors.orange,
body: SingleChildScrollView(
child: Column(
children: [
Container(
margin: const EdgeInsets.only(
left: 8.0, right: 8.0, top: 10.0, bottom: 5.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white.withOpacity(0.2),
),
child: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text('Benutzer:',
style: TextStyle(fontWeight: FontWeight.bold)),
),
),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.only(
bottom: 10.0, left: 10.0, right: 10.0),
child: Text(''),
),
),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text('Spitzname:',
style: TextStyle(fontWeight: FontWeight.bold)),
),
),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.only(
bottom: 10.0, left: 10.0, right: 10.0),
child: Text(''),
),
),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text('E-Mail:',
style: TextStyle(fontWeight: FontWeight.bold)),
),
),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.only(
bottom: 10.0, left: 10.0, right: 10.0),
child: Text(''), // here should print the email address from firestore
),
),
Text(''),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text('Hinweis: ',
style: TextStyle(fontWeight: FontWeight.bold)),
),
),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
'Wenn Du dein Konto löschen oder dein Passwort zurücksetzen möchtest, schreibe bitte eine Email an medien#visuhome.de'),
),
),
Text(''),
],
)),
Container(
margin: const EdgeInsets.only(
left: 8.0, right: 8.0, top: 3.0, bottom: 3.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white.withOpacity(0.2),
),
child: Row(
children: [
ButtonNutzung(),
Text("Nutzungsbedingungen",
style:
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
],
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Divider(),
),
SizedBox(height: 10),
if (user.uid != null)
Text(
'Cloud User-ID: ' + user.uid,
style: TextStyle(color: Colors.black),
),
SizedBox(height: 10),
Padding(
padding: const EdgeInsets.all(10.0),
child: Divider(),
),
GestureDetector(
onTap: _launchURL2,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(left: 20.0, right: 20.0),
child: Text(
'created by visuhome',
style: TextStyle(
fontWeight: FontWeight.w300,
fontSize: 12,
color: Colors.black),
),
),
Image(
//AssetImage oder SizedBox mit child und width
image: AssetImage('assets/visuhome_logo_black_flutter.png'),
fit: BoxFit.fitHeight,
height: 30,
),
Padding(
padding: const EdgeInsets.only(left: 20.0, right: 20.0),
child: Text(
'Version 1.0',
style: TextStyle(
fontWeight: FontWeight.w300,
fontSize: 12,
color: Colors.black),
),
),
],
),
),
],
),
),
);
}
}
As you can see I do get information from the FirebaseAuth.instance.currentUser, so the userid from the logged-in user is shown. But I want the information from the userdata in firestore too.
Can anybody help with this basic firestore-trick I guess? I'm new in flutter. Tried a lot but cannot find solutions which fit for my example. Thanks a lot
You should to create query to Firestore and get user details.
If you know the user ID, you can call doc function to create query.
#override
Widget build(BuildContext context) {
CollectionReference users = FirebaseFirestore.instance.collection('users');
return FutureBuilder<DocumentSnapshot>(
future: users.doc(documentId).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data = snapshot.data.data();
return Text("Full Name: ${data['full_name']} ${data['last_name']}");
}
return Text("loading");
},
);
}
Or use where expression to find user by its attributes (for example email):
FirebaseFirestore.instance
.collection('users')
.where('email', isEqualTo: "test#yahoo.de")
.get()
For more details check Firestore tutorial
I have been trying to find a way on how I can put a navigation in "Widget CardUI" because I want it to redirect the user to another page when they click on it. However, when I try to put the usual Navigator.push(context, MaterialPageRoute(builder: (context)=>PageName()));", it tells me that the context is undefined.
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: ()
{Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context)=>homepage()));}),
title: Text("Creator's Club"),
backgroundColor: Color(0xff2657ce),
elevation: 0,),
body: Container(
padding: EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Visual Arts', style: TextStyle(
color: Color(0xff2657ce),
fontSize: 27,
),),
Text('Choose which course you want to study.', style: TextStyle(
color: Colors.black.withOpacity(0.6),
fontSize: 20
),),
SizedBox(height: 10),
Expanded(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
coursesList.length == 0 ? Center(child: Text("Loading...", style: TextStyle(fontSize: 15),)): ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: coursesList.length,
itemBuilder: (_, index) {
return CardUI(coursesList[index].courseName, coursesList[index].teacher, coursesList[index].category);
}
)
]
),
),
),
]
)
)
);
}
}
Widget CardUI (String courseName, String teacher, String category){
return Card(
elevation: 1,
margin: EdgeInsets.all(5),
color: Color(0xffd3defa),
child: Container(
color: Colors.white,
margin: EdgeInsets.all(1),
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: Color(0xffd3defa),
borderRadius: BorderRadius.all(Radius.circular(17)),
),
child: IconButton(
icon: Icon(
Icons.star_border_rounded,
color: Color(0xff2657ce),
),
),
),
SizedBox(width: 15,),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
child: InkWell(
onTap: () {},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(courseName,
style: TextStyle(fontSize: 18)),
SizedBox(height: 5),
Text(teacher, style: TextStyle(
fontSize: 15, color: Colors.grey)),
SizedBox(height: 5),
],
),
)
)
]
)
]
)
],
)
),
);
}
Additionally, is there a way on how I can put an if else condition in the Inkwell onTap? In my code, a bunch of courses are being displayed from realtime database and I want to click on just one of it. In my current code, the Inkwell applies to all the cards being displayed but I just want it to be on one. Are there any alternatives besides using Inkwell?
Try to call
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context)=>homepage()));
},
without pop before.
Future<List<DocumentSnapshot>> getData() async {
var firestore = Firestore.instance;
QuerySnapshot qn = await firestore
.collection("LiveGames")
.where("Title", isEqualTo: "Solo")
.getDocuments();
return qn.documents;
}
I have extracted the data using this function getData() to use it in the FutureBuilder.
FutureBuilder(
future: getData(),
builder: (_, AsyncSnapshot<List<DocumentSnapshot>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Padding(
padding: const EdgeInsets.only(
top: 50,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Center(
child: SpinKitCircle(
color: Color.fromRGBO(91, 74, 127, 10),
size: 50.0,
),
),
],
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (_, index) {
return SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.all(10),
height: 185,
width: double.infinity,
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10)),
color: Colors.blueGrey.shade800,
),
height: 150,
width: double.infinity,
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: <Widget>[
SizedBox(
height: 6,
),
Expanded(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Date",
style: TextStyle(
color: Colors.white,
)),
Text(
snapshot.data[index]
.data["GameDate"],
style: TextStyle(
color: Colors.white,
)),
],
),
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Time",
style: TextStyle(
color: Colors.white,
)),
Text(
snapshot.data[index]
.data["GameTime"],
style: TextStyle(
color: Colors.white,
)),
],
),
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Map",
style: TextStyle(
color: Colors.white,
)),
Text(
snapshot.data[index]
.data["MapName"],
style: TextStyle(
color: Colors.white,
)),
],
),
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Mode",
style: TextStyle(
color: Colors.white,
)),
Text(
snapshot.data[index]
.data["GameMode"],
style: TextStyle(
color: Colors.white,
)),
],
)
],
),
),
Divider(
color: Colors.white,
),
Expanded(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Players Joined",
style: TextStyle(
color: Colors.white,
)),
Text(
"${snapshot.data[index].data["RemainingPlayers"]}",
style: TextStyle(
color: Colors.white,
)),
],
),
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Winning",
style: TextStyle(
color: Colors.white,
)),
Expanded(
child: FlatButton(
child: Icon(
Icons.arrow_drop_down,
size: 18,
color: Colors.white,
),
onPressed: () {
showModalBottomSheet(
backgroundColor:
Colors.orange
.shade500,
shape:
RoundedRectangleBorder(
borderRadius:
BorderRadius
.only(
topLeft:
Radius.circular(
15),
topRight:
Radius.circular(
15),
)),
context: context,
builder: (context) {
return Container(
child: Column(
children: <Widget>[
],
),
);
},
);
}))
],
),
Column(
children: <Widget>[
SizedBox(
height: 5,
),
Text("Remaining Players",
style: TextStyle(
color: Colors.white,
)),
Text(
"${snapshot.data[index].data["TotalSeats"]}",
style: TextStyle(
color: Colors.white,
)),
],
)
],
),
),
Divider(
color: Colors.white,
),
Expanded(
child: Container(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
children: <Widget>[
Text("Per Kill",
style: TextStyle(
color: Colors.white,
)),
Text(
"₹ ${snapshot.data[index].data["PerKill"]}",
style: TextStyle(
color: Colors.white,
)),
],
),
Column(
children: <Widget>[
Text("Entry Fees",
style: TextStyle(
color: Colors.white,
)),
Text(
"₹ ${snapshot.data[index].data["Entryfees"]}",
style: TextStyle(
color: Colors.white,
)),
],
),
],
),
),
),
],
),
),
Container(
margin: EdgeInsets.only(top: 150),
height: 35,
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10)),
color: Colors.orange,
),
child: Padding(
padding: const EdgeInsets.only(left: 125),
child: InkWell(
onTap: () {
print("Solo Joined");
},
child: Text(
"Join Contest",
style: TextStyle(
color: Colors.white,
fontSize: 25,
fontFamily: "OpenSans",
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
),
],
),
);
});
}
},
),
And then i have displayed some Widgets according to the data.
But in database i have some rank values and i want to display the data in the bottomsheet if the rank from 2 to 10 and 11 to 20 and 21 to 40 are zeros i do not want to display in the bottom sheet only rank1 player i want it to display but if Rank1 player and all the players from rank 1 to 40 some values are there then i have to display the all the data in the bottomSheet
From your question, I don't see any issues on using FutureBuilder in Flutter. The issue here seems to lean more on how you can manage your Firestore data to be displayed.
If you'd like to filter out Players to be displayed base from their Rank. What you can do here is create a Collections for Players where you can sort them by Rank.
Say you'd only like to display Players with Rank 1 in your List.
FirebaseFirestore.instance
.collection('players')
.where('rank', isEqualTo: 1)
.snapshots()
For Rank with ranges, say Ranks 2-10, compound queries can be utilized. For querying in Flutter, you can check the API reference for its equivalence.
FirebaseFirestore.instance
.collection('players')
.where('rank', isGreaterThanOrEqualTo: 2)
.where('rank', isLessThanOrEqualTo: 10)
.snapshots()
Here's a sample that I posted previously that filters and displays all carModels base from the selected carMake. It uses StreamBuilder though. I'm curious on your choice for using FutureBuilder instead of StreamBuilder.
Try the following example:
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<QuerySnapshot>(
future: FirebaseFirestore
.instance
.collection('users') // 👈 Your collection name here
.get(),
builder: (_, snapshot) {
if (snapshot.hasError) return Text('Error = ${snapshot.error}');
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
}
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return ListTile(
title: Text(data['avatar']), // 👈 Your valid data here
);
}).toList());
},
)),
);
}
Also refer: How to use StreamBuilder and FutureBuilder for single and multiple documents
how to print value of field.
what I have tried :
print(documents[index].data['Likes.$usersId']);
actually I need this for toggle between icons.
thanks.
Update:
Widget build(BuildContext context) {
return Container(
child: StreamBuilder<QuerySnapshot>(
stream: UserManagement().getPostsStream(),
builder: (_, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else {
final List<DocumentSnapshot> documents = snapshot.data.documents;
return ListView.builder(
itemCount: documents.length,
itemBuilder: (_, index) {
return Card(
elevation: 4,
child: Padding(
padding: EdgeInsets.only(left: 10.0, top: 10),
child: InkWell(
onTap: () => navigateToDetail(
documents[index],
documents[index].data["Userid"],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Row(
children: <Widget>[
Container(
width: 45,
height: 45,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
documents[index].data["User Pic"]),
fit: BoxFit.cover,
),
borderRadius: BorderRadius.all(
Radius.circular(50.5)),
),
),
Padding(
padding: EdgeInsets.only(left: 15),
child: Text(
documents[index].data["Name"],
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 18),
),
),
],
),
Padding(
padding: EdgeInsets.only(left: 60, bottom: 10),
child: Text(
DateFormat.yMMMd().add_jm().format(
DateTime.parse(documents[index]
.data["Creation Time"]
.toDate()
.toString())),
style: TextStyle(
color: Colors.black38, fontSize: 12),
),
),
Flexible(
child: Padding(
padding: EdgeInsets.only(left: 75, right: 15),
child: Text(
documents[index].data["Description"],
style: TextStyle(fontSize: 16),
),
),
),
Padding(
padding: EdgeInsets.only(
left: 75, top: 15, bottom: 8),
child: Text(
documents.length.toString() +
"Files uploaded",
style: TextStyle(
color: Colors.blueAccent,
fontSize: 14,
fontStyle: FontStyle.italic),
),
),
Divider(),
new Row(
children: <Widget>[
Expanded(
child: Row(
children: <Widget>[
IconButton(
onPressed: () {
print(documents[index].data['Likes.$usersId']);
},
icon: documents[index].data['$usersId'] == true ? Icon(Icons.favorite,
color: Colors.redAccent,
size: 23.0) : Icon(Icons.favorite_border,
color: Colors.redAccent,
size: 23.0)
),
/*Text(documents[index].data['Likes'].length.toString()),*/
],
),
),
Expanded(
child: IconButton(
onPressed: () {
navigateToDetail(documents[index],
documents[index].data["Userid"],);
},
icon: Icon(
Icons.chat_bubble_outline,
color: Colors.blue,
size: 23.0,
),
),
),
Expanded(
child: IconButton(
onPressed: () {},
icon: Icon(
Icons.near_me,
color: Colors.blue,
size: 23.0,
),
),
),
],
),
],
),
),
),
);
});
}
}),
);
}
This is to get Posts :
Stream<QuerySnapshot> getPostsStream() {
return Firestore.instance.collection("Posts").orderBy(
"Creation Time", descending: true).snapshots();
}
Change this:
print(documents[index].data['Likes.$usersId']);
into this:
print(documents[index].data['Likes'][usersId]);
Raised button taking too much width and I want to decrease according to my layout...
ButtonTheme(
minWidth: 16.0,
height: 30.0,
child: RaisedButton(
onPressed:()=>print("a"),
child: new Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 6.0),
child: Text('SORT BY',style: TextStyle(fontSize: 12.0),),
),
Icon(Icons.keyboard_arrow_down,size: 20.0,),
],
),
),
),
I got the answer
We need to add padding in Raised button for removing default padding
ButtonTheme(
minWidth: 16.0,
height: 30.0,
child: RaisedButton(
padding: const EdgeInsets.all(8.0),
onPressed: () => print("a"),
child: new Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 6.0),
child: Icon(
Icons.filter,
size: 16.0,
),
),
Text(
'FILTER',
style: TextStyle(fontSize: 12.0),
),
],
),
),
),
You are using Row widget inside your RaisedButton and it's taking the maximum width, you can fix it using the min space mainAxisSize: MainAxisSize.min like this:
ButtonTheme(
minWidth: 16.0,
height: 30.0,
child: RaisedButton(
onPressed: () => print("a"),
child: new Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 6.0),
child: Text(
'SORT BY',
style: TextStyle(fontSize: 12.0),
),
),
Icon(
Icons.keyboard_arrow_down,
size: 20.0,
),
],
),
),
),