How can I use a appear in another widget? - firebase

Im trying to use a appbar widget in another widget so my code is more clear. But the question is how can I do this ?
Heres my app bar widget :
class thisappbar extends StatelessWidget {
thisappbar(this.isMe, this.username, {this.key});
final Key key;
final bool isMe;
String username;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
automaticallyImplyLeading: false,
backgroundColor: Colors.white,
flexibleSpace: SafeArea(
child: Container(
padding: EdgeInsets.only(right: 16),
child: Row(
children: <Widget>[
IconButton(
onPressed: (){
Navigator.pop(context);
},
----------
And heres the way I wanna use it :
class ChatScreen extends StatelessWidget {
static const route = '/messages';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(thisappbar(),
),
body: Container(
child: Column(
children: <Widget>[
Expanded(child: Messages()),
NewMessage(),
],
)),
);
}
}
Hope anyone can help thanks!
This is how my methods look now first the app bar widget after editing some changes from user #Steve Nosse :
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
CustomAppBar({this.key, this.isMe, this.username}) : super(key: key);
final Key key;
final bool isMe;
String username;
#override
Widget build(BuildContext context) {
/// Build you AppBar widget here
return Scaffold(
appBar: AppBar(
elevation: 0,
automaticallyImplyLeading: false,
backgroundColor: Colors.white,
flexibleSpace: SafeArea(
child: Container(
padding: EdgeInsets.only(right: 16),
child: Row(
children: <Widget>[
IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back, color: Colors.black,),
),
SizedBox(width: 2,),
CircleAvatar(
backgroundImage: NetworkImage(
'https://randomuser.me/api/portraits/men/5.jpg'),
maxRadius: 20,
),
SizedBox(width: 12,),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
username, style: TextStyle(
fontSize: 16, fontWeight: FontWeight.w600),),
SizedBox(height: 6,),
Text("Online", style: TextStyle(
color: Colors.grey.shade600, fontSize: 13),),
],
),
),
Icon(Icons.settings, color: Colors.black54,),
],
),
),
),
),
);
}
#override
Size get preferredSize => Size.fromHeight(56);
}
And heres where I use the appbar widget:
class ChatScreen extends StatelessWidget {
static const route = '/messages';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(),
body: Container(
child: Column(
children: <Widget>[
Expanded(child: Messages()),
NewMessage(),
],
)),
);
}
}
And this is the error :
======== Exception caught by widgets library =======================================================
The following assertion was thrown building CustomAppBar(dirty):
A non-null String must be provided to a Text widget.
'package:flutter/src/widgets/text.dart':
Failed assertion: line 378 pos 10: 'data != null'
The relevant error-causing widget was:
CustomAppBar file:///Users/name/StudioProjects/project/lib/seitenleiste/nachrichten.dart:390:15
When the exception was thrown, this was the stack:
#2 new Text (package:flutter/src/widgets/text.dart:378:10)
#3 CustomAppBar.build (package:project/seitenleiste/nachrichten.dart:357:23)
#4 StatelessElement.build (package:flutter/src/widgets/framework.dart:4646:28)
#5 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4572:15)
#6 Element.rebuild (package:flutter/src/widgets/framework.dart:4265:5)
...

You can try this:
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
CustomAppBar({this.key, this.isMe, this.username}) : super(key: key);
final Key key;
final bool isMe;
String username;
#override
Widget build(BuildContext context) {
/// Build you AppBar widget here
return Container();
}
#override
Size get preferredSize => Size.fromHeight(56);
}
Your CustomAppBar, as any other class, can by designed to take parameters from the outside to build itself.
The fact that it implements the PreferredSizeWidget allows us to easily use it as a parameter for the appBar attribute of the Scaffold widget.

Related

Flutter/Firebase - Right Track?

At 54 I'm self-learning Flutter and have come a long way. I am stuck (again) with a speed-bump concerning my implementation of Firebase. Although I am getting the very basic of displaying a line of data for each record the problem is getting to the details of each record. I believe the issue is that I am not referencing the record ID.
When looking at endless examples I also believe my code to display a ListView of records is bloated making it more difficult to grab a record and display all fields (edit screen).
I want to click the "Walsh-Test" links to view all fields and update. I can create a new edit/update screen my initial problem is opening the screen to the selected record.
Any advice would be greatly appreciated.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/rendering.dart';
class MeterReadHomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Color(0xff4367b1),
automaticallyImplyLeading: false,
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Icon(
Icons.arrow_back,
color: Colors.white,
),
),
title: Text(
"WelakaOne",
style: TextStyle(
color: Colors.white,
),
),
),
body: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('meter_reads')
.orderBy('accountname')
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return Padding(
padding: const EdgeInsets.fromLTRB(6, 20, 0, 0),
child: Container(
child: GestureDetector(
onTap: () {},
child: ListView(
children: snapshot.data.docs.map(
(document) {
return Row(
children: [
Container(
width: 50,
child: Icon(
Icons.access_alarm,
size: 36,
color: Color(0xff4367b1),
),
),
Container(
child: Text(
document['accountname'],
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Color(0xff4367b1),
),
),
),
SizedBox(height: 44),
],
);
},
).toList(),
),
),
),
);
},
),
);
}
}
[![Flutter/Firebase/Open to Selected Record][1]][1]
I understand that you want to go to another page (Edit Screen) onTapping the alarm tile.
So, my suggestion is to use A ListTile widget instead of the row widget you are using.
You can read about ListTile's onTap property, here
Regarding your routing to a new screen/page, you'll have to make use of MaterialPageRoute to create a new route and using Navigator's push method you can push it onto your Material App.
Attaching an example code that uses Navigator to go to different pages, you need the BuildContext of your app. Here is an example of how you can get it:
import 'package:flutter/material.dart';
import 'package:rate_your_professor/screens/firstScreen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Some App',
home: SomeApp(),
);
}
}
class SomeApp extends StatelessWidget {
Widget getListView(BuildContext context) {
var listView = ListView(
children: <Widget>[
Text(
"XXXXXXXXXXXXXXX",
textDirection: TextDirection.rtl,
textAlign: TextAlign.center,
),
ListTile(
leading: Icon(Icons.location_city),
title: Text("XXXXX ", textDirection: TextDirection.rtl),
subtitle: Text(
"XXXXXXXXXX",
textDirection: TextDirection.rtl,
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => YourNewPage(),
),
);
},
),
],
);
return listView;
}
#override
Widget build(BuildContext context) {
return Scaffold(body: getListView(context));
}
}

How can I show the user name of the other user?

I have a app and in that a chat function were chat working correctly and user name correctly diplayed. But now im trying to add a appBar and im getting an error. What I want is trying to build the name of the other user and not mine . So an example: I chat with my friend and in the app bar I wanna see his name so I know with how Im chatting . but how do I do that?. Heres how my chat app locks at the moment.
So heres how I use the username in chat bubble and it works fine :
class MessageBubble extends StatelessWidget {
MessageBubble(this.message, this.isMe, this.username, {this.key});
final Key key;
final String message;
final bool isMe;
String username;
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment:
isMe ? MainAxisAlignment.end : MainAxisAlignment.start,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: isMe ? Colors.grey[300] : Colors.black,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
bottomLeft:
!isMe ? Radius.circular(0) : Radius.circular(12),
bottomRight:
isMe ? Radius.circular(0) : Radius.circular(12),
)),
width: 140,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 16),
margin: EdgeInsets.symmetric(vertical: 4, horizontal: 8),
child: Column(
crossAxisAlignment:
isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Text(
username,
style: TextStyle(
color: isMe
? Colors.black
: Colors.white,
fontWeight: FontWeight.bold),
),
Text(
message,
style: TextStyle(
color: isMe
? Colors.black
: Colors.white),
textAlign: isMe ? TextAlign.end : TextAlign.start,
),
]))
]);
}
}
It displayed the correct username and the correct user message .
And heres how I wanna use it in the app bar:
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
CustomAppBar({this.key, this.username,this.isMe} ) : super(key: key);
final Key key;
final bool isMe;
final String username;
//String username;
#override
Widget build(BuildContext context) {
/// Build you AppBar widget here
return Scaffold(
appBar: AppBar(
elevation: 0,
automaticallyImplyLeading: false,
backgroundColor: Colors.white,
flexibleSpace: SafeArea(
child: Container(
padding: EdgeInsets.only(right: 16),
child: Row(
children: <Widget>[
IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back, color: Colors.black,),
),
SizedBox(width: 2,),
CircleAvatar(
backgroundImage: NetworkImage(
'https://randomuser.me/api/portraits/men/5.jpg'),
maxRadius: 20,
),
SizedBox(width: 12,),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
username, style: TextStyle(
fontSize: 16, fontWeight: FontWeight.w600),),
SizedBox(height: 6,),
Text("Online", style: TextStyle(
color: Colors.grey.shade600, fontSize: 13),),
],
),
),
Icon(Icons.settings, color: Colors.black54,),
],
),
),
),
),
);
}
#override
Size get preferredSize => Size.fromHeight(56);
}
And heres I wanna displayed it :
class ChatScreen extends StatelessWidget {
static const route = '/messages';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar:CustomAppBar()
,
body: Container(
child: Column(
children: <Widget>[
Expanded(child: Messages()),
NewMessage(),
],
),
),
);
}
}
I think you need to pass the username as String (and other parameters) in the CustomAppBar constructor like this:
class ChatScreen extends StatelessWidget {
static const route = '/messages';
final String username;
ChatScreen({#required this.username});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
username: username, // This is dynamic..
isMe: true,
),
body: Container(
child: Column(
children: <Widget>[
Expanded(child: Messages()),
NewMessage(),
],
),
),
);
}
}
EDIT
You need to get first the username of the other user and then you can create your ChatScreen:
//...some code...
String username = getUsername(); // This is your method to get the username
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ChatScreen(username: username)));
In your code, when you are calling CustomAppBar() you are not passing any info/strings to it, that's causing your null error regarding a null string.
It should be i.e CustomAppBar (userName).

How can I add data from the Firebase database in a reversed order? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am currently developing a chat app. The problem is, that when someone types something it shows randomly on the chat screen (after a user registered and logged in).
I want it to look like a normal chat app, so the last message should be at the bottom of the screen. I even reversed the data and list view, but it didn't work.
My code:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:naber/constants.dart';
final _firestore=FirebaseFirestore.instance;
User loggedInUser;
class ChatScreen extends StatefulWidget {
static String id="chat_screen";
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final messageTextController = TextEditingController();
final _auth = FirebaseAuth.instance;
String messageText;
void initState(){
super.initState();
getCurrentUser();
}
void getCurrentUser()async{
try{
final currentUser = await _auth.currentUser;
if(currentUser!=null){
loggedInUser=currentUser;
}
}
catch(e){
print(e);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
_auth.signOut();
Navigator.pop(context);
}),
],
title: Text('Chat'),
backgroundColor: Colors.lightBlueAccent,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
MessagesStream(),
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: messageTextController,
onChanged: (value) {
messageText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
FlatButton(
onPressed: () {
messageTextController.clear();
_firestore.collection('messages').add({
'text': messageText,
'sender': loggedInUser.email,
});
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
);
}
}
class MessagesStream extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('messages').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
}
final messages = snapshot.data.docs.reversed;
List<MessageBubble> messageBubbles = [];
for (var message in messages) {
final messageText = message.data()['text'];
final messageSender = message.data()['sender'];
final currentUser = loggedInUser.email;
final messageBubble = MessageBubble(
sender: messageSender,
text: messageText,
isMe: currentUser == messageSender,
);
messageBubbles.add(messageBubble);
}
return Expanded(
child: ListView(
reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
children: messageBubbles,
),
);
},
);
}
}
class MessageBubble extends StatelessWidget {
MessageBubble({this.sender, this.text, this.isMe});
final String sender;
final String text;
final bool isMe;
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment:
isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Text(
sender,
style: TextStyle(
fontSize: 12.0,
color: Colors.black54,
),
),
Material(
borderRadius: isMe
? BorderRadius.only(
topLeft: Radius.circular(30.0),
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0))
: BorderRadius.only(
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
elevation: 5.0,
color: isMe ? Colors.lightBlueAccent : Colors.white,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
child: Text(
text,
style: TextStyle(
color: isMe ? Colors.white : Colors.black54,
fontSize: 15.0,
),
),
),
),
],
),
);
}
}
You add messages with:
_firestore.collection('messages').add({
'text': messageText,
'sender': loggedInUser.email,
});
Firestore doesn't have any built-in default ordering for documents. If you want to be able to order the documents, you will need to add a value to each document to allow that.
For example, you could add a timestamp of when the document was created with:
_firestore.collection('messages').add({
'text': messageText,
'sender': loggedInUser.email,
'createdAt': FieldValue.serverTimestamp()
});
By using FieldValue.serverTimestamp() the server will automatically populate this field, which you can then use when reading the data with:
stream: _firestore.collection('messages').orderBy('createdAt', descending: true).snapshots()

The following NoSuchMethodError was thrown building MessageBubble(dirty): The getter 'millisecondsSinceEpoch' was called on null

So, i am creating an mobile chat app (only to learn). I am trying to make it push the timestamp of the message (from firebase) to display it on the screen using the time_formatter package. It is actually working, but everytime i send a message, the emulator screen gets red for about 1 second and this error is thrown:
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building MessageBubble(dirty):
The getter 'millisecondsSinceEpoch' was called on null.
Receiver: null
Tried calling: millisecondsSinceEpoch
The relevant error-causing widget was:
MessageBubble file:///C:/Users/cauer/Desktop/Apps-Flutter/flash_chat_flutter/lib/screens/chat_screen.dart:141:33
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 MessageBubble.build (package:flash_chat/screens/chat_screen.dart:208:32)
#2 StatelessElement.build (package:flutter/src/widgets/framework.dart:4576:28)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4502:15)
#4 Element.rebuild (package:flutter/src/widgets/framework.dart:4218:5)
After this, it shows exactly what I want on the screen, but I do want to know what is going on and fix it. Sorry for anything, I'm knew here. If needed, I post more of my code or any other info, but I im quite certain that it is caused by something here.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flash_chat/constants.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:time_formatter/time_formatter.dart';
final _firestore = Firestore.instance;
FirebaseUser loggedInUser;
class ChatScreen extends StatefulWidget {
static String id = 'chat_screen';
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final messageTextController = TextEditingController();
final _auth = FirebaseAuth.instance;
String messageText;
#override
void initState() {
super.initState();
getCurrentUser();
}
void getCurrentUser() async {
try {
final user = await _auth.currentUser();
if (user != null) {
loggedInUser = user;
}
} catch (e) {
print(e);
}
}
void messageStream() async {
await for (var snapshot in _firestore.collection('messages').snapshots()) {
for (var message in snapshot.documents) {
print(message.data);
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
_auth.signOut();
Navigator.pop(context);
}),
],
title: Text('⚡️Chat'),
backgroundColor: Colors.lightBlueAccent,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
MessagesStream(),
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: messageTextController,
onChanged: (value) {
messageText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
FlatButton(
onPressed: () {
messageTextController.clear();
_firestore.collection('messages').add({
'text': messageText,
'sender': loggedInUser.email,
'timestamp': FieldValue.serverTimestamp(),
}).then((value) => print('${value.documentID} added'));
messageTextController.clear();
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
);
}
}
class MessagesStream extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _firestore
.collection('messages')
.orderBy('timestamp', descending: false)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
}
final messages = snapshot.data.documents.reversed;
List<MessageBubble> messageBubbles = [];
for (var message in messages) {
final messageText = message.data['text'];
final messageSender = message.data['sender'];
final messageTime = message.data['timestamp']; //add this
final currentUser = loggedInUser.email;
final messageBubble = MessageBubble(
sender: messageSender,
text: messageText,
isMe: currentUser == messageSender,
time: messageTime,
);
messageBubbles.add(messageBubble);
}
return Expanded(
child: ListView(
reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
children: messageBubbles,
),
);
},
);
}
}
class MessageBubble extends StatelessWidget {
MessageBubble({this.sender, this.text, this.isMe, this.time});
final String sender;
final String text;
final bool isMe;
final Timestamp time;
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment:
isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Text(
'$sender',
style: TextStyle(
fontSize: 12.0,
color: Colors.black54,
),
),
Material(
borderRadius: isMe
? BorderRadius.only(
topLeft: Radius.circular(30.0),
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0))
: BorderRadius.only(
topRight: Radius.circular(30.0),
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0)),
elevation: 5.0,
color: isMe ? Colors.lightBlueAccent : Colors.white,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 20.0),
child: Text(
'$text',
style: TextStyle(
color: isMe ? Colors.white : Colors.black54,
fontSize: 15,
),
),
),
),
Text(
'${formatTime(time.millisecondsSinceEpoch)}',
style: TextStyle(
fontSize: 11.0,
color: Colors.black54,
),
),
],
),
);
}
}
Any kind of help will be appreciated, already looked for an answer and couldn't find it.
This is what the screen displays in the moment that the message is sent
Modify your MessageBubble constructor as such
MessageBubble({this.sender, this.text, this.isMe, Timestamp time}):time = time ?? Timestamp.now();
The problem is FieldValue.serverTimestamp() is null when firestore writes the data locally
I think this should work.
Make a separate function, so that you can handle if time is null.
Widget handleerr() async{
await Future.delayed(const Duration(milliseconds: 2000), () {
setState(() {
Text(
'${formatTime(time.millisecondsSinceEpoch)}',
style: TextStyle(
fontSize: 11.0,
color: Colors.black54,
)
});
});
}

Flutter Passing Document ID in Firestore Query

I am trying to figure out how to do this.
If I pass the document ID hardcoded it works. But Since I have multiple pages, I am trying to figure out how to pass it and then query it..
My main page has the following.
import 'package:flutter/material.dart';
import 'package:onlytag2/pages/category.dart';
import 'package:onlytag2/widget/maincard.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:async';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
StreamSubscription<QuerySnapshot> subscription;
List<DocumentSnapshot> snapshot;
Query collectionReference = Firestore.instance.collection("mainCategories").orderBy("title");
void initState() {
subscription = collectionReference.snapshots().listen((datasnapshot) {
setState(() {
snapshot = datasnapshot.documents;
});
});
super.initState();
}
#override
void dispose() {
subscription.cancel(); //Streams must be closed when not needed
super.dispose();
}
passData(DocumentSnapshot snap, String cat, String title) {
print(cat);
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => Category(snapshot: snap, category: cat, title: title,)));
}
#override
Widget build(BuildContext context) {
if (snapshot == null) return Center(
child: Container(
color: Colors.black,
alignment: AlignmentDirectional(0.0, 0.0),
child: Container(
color: Colors.black,
constraints: BoxConstraints(
maxHeight: 300.0,
maxWidth: 200.0,
minWidth: 150.0,
minHeight: 150.0
),
child: CircularProgressIndicator(),
),
),
);
return Scaffold(
backgroundColor: Color(0xff0E0E0F),
appBar: AppBar(
centerTitle: true,
backgroundColor: Colors.black,
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"#",
style: TextStyle(
fontSize: 25, color: Color(0xffff9900), fontFamily: 'Dokyo'),
),
Text(
"onlytags",
style: TextStyle(color: Colors.white, fontFamily: 'Dokyo'),
)
],
),
),
body: Column(
children: <Widget>[
Expanded(
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: snapshot.length,
itemBuilder: (context, index) {
return InkWell(
onTap: () => passData(snapshot[index], snapshot[index].documentID.toString(), snapshot[index].data["title"] ),
child: MainCard(
title: snapshot[index].data["title"],
subtitle: snapshot[index].data["subTitle"],
image: snapshot[index].data["image"],
),
);
}),
),
],
),
),
],
),
);
}
}
The category widget is where I am having the problem.
Comment Listed where I am having the problem.
import 'package:flutter/material.dart';
import 'package:onlytag2/widget/sub.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:async';
class Category extends StatefulWidget {
DocumentSnapshot snapshot;
final String category;
final String title;
Category({this.snapshot, this.category, this.title});
#override
_CategoryState createState() => _CategoryState();
}
class _CategoryState extends State<Category>{
StreamSubscription<QuerySnapshot> subscription;
List<DocumentSnapshot> snapshot;
//How do I get the category passed properly? I know it is the Document ID, but since it changes based on what button is pressed before,
//I cant figure out how to pass it..
Query collectionReference = Firestore.instance.collection("mainCategories").document(widget.category).collection("subCategories").orderBy("title");
void initState() {
subscription = collectionReference.snapshots().listen((datasnapshot) {
setState(() {
snapshot = datasnapshot.documents;
});
});
super.initState();
}
#override
void dispose() {
subscription.cancel(); //Streams must be closed when not needed
super.dispose();
}
#override
Widget build(BuildContext context) {
if (snapshot == null) return Center(
child: Container(
color: Colors.black,
alignment: AlignmentDirectional(0.0, 0.0),
child: Container(
color: Colors.black,
constraints: BoxConstraints(
maxHeight: 300.0,
maxWidth: 200.0,
minWidth: 150.0,
minHeight: 150.0
),
child: CircularProgressIndicator(),
),
),
);
return Scaffold(
backgroundColor: Color(0xff0E0E0F),
appBar: AppBar(
iconTheme: IconThemeData(
color: Color(0xffff9900),
),
centerTitle: true,
backgroundColor: Colors.black,
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
"#", style: TextStyle(fontSize: 25, color: Color(0xffff9900), fontFamily: 'Dokyo'),
),
Text(widget.title.toLowerCase(), style: TextStyle(color: Colors.white, fontFamily: 'Dokyo'),)
],
),
),
body: Column(
children: <Widget>[
Expanded(
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: snapshot.length,
itemBuilder: (context, index) {
return Sub(
title: snapshot[index].data["title"],
subtitle: snapshot[index].data["subTitle"],
image: snapshot[index].data["image"],
);
}),
),
Padding(padding: EdgeInsets.fromLTRB(0, 0, 0, 15),)
],
),
),
],
),
);
}
}
I have realised that the code looks shady on the comment so let me make an answer.
What you are trying to do is currently not supported in flutter as can be seen at these GitHub issues 1 and 2.
Change your code to,
class _CategoryState extends State<Category>{
StreamSubscription<QuerySnapshot> subscription;
List<DocumentSnapshot> snapshot;
Query collectionReference;
void initState() {
collectionReference = Firestore.instance.collection("mainCategories").document(widget.category).collection("subCategories").orderBy("title");
subscription = collectionReference.snapshots().listen((datasnapshot) {
setState(() {
snapshot = datasnapshot.documents;
});
});
super.initState();
}
...
Hope this helps.

Resources