我刚刚根据教程完成了这个基本的聊天应用程序,但我的消息并不总是从底部开始。
当我删除时,保存并重新添加 .reversed 在这一行:
final messages = snapshot.data.documents.reversed;
Run Code Online (Sandbox Code Playgroud)
那么它似乎重新排序正确,但下一条消息又是随机的。
唯一的区别是我使用了更新的 firebase 插件。
//消息流代码
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.lightBlue,
),
);
}
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 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(vertical: 20.0, horizontal: 10.0),
children: messageBubbles,
),
);
},
);
}
}
Run Code Online (Sandbox Code Playgroud)
除了随机顺序外,一切正常,消息保存在 firebase 中。也许我需要添加时间码或其他东西才能使它工作。
任何帮助表示赞赏 - 谢谢。
GAU*_*SHI 10
应用此代码后,就像安吉拉在她的课程视频中所做的那样,删除 firebase 中的数据库。然后重新启动应用程序。你的应用程序会工作。此外,在代码中,我添加了有关您必须添加的内容的说明。仅添加它们。我遇到了同样的问题,所以我在编码器的帮助下解决了这个问题。所以它也适用于你的代码。
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';
final _fireStore = Firestore.instance;
FirebaseUser loggedInUser;
class ChatScreen extends StatefulWidget {
static String chatScreen = 'ChatScreenpage1';
@override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final messageTextEditingController = TextEditingController();
String messageText;
final _auth = FirebaseAuth.instance;
@override
void initState() {
super.initState();
getUserDetail();
}
void getUserDetail() async {
try {
final createdUser = await _auth.currentUser();
if (createdUser != null) {
loggedInUser = createdUser;
}
} 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>[
StreambuilderClass(),
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: messageTextEditingController,
onChanged: (value) {
messageText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
FlatButton(
onPressed: () {
messageTextEditingController.clear();
_fireStore.collection('messages').add({
'sender': loggedInUser.email,
'text': messageText,
'time': FieldValue.serverTimestamp() //add this
});
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
);
}
}
class StreambuilderClass extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _fireStore
.collection('messages')
.orderBy('time', descending: false)//add this
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.blueAccent,
),
);
}
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['time'] as Timestamp; //add this
final currentUser = loggedInUser.email;
final messageBubble = MessageBubble(
sender: messageSender,
text: messageText,
isMe: currentUser == messageSender,
time: messageTime, //add this
);
messageBubbles.add(messageBubble);
}
return Expanded(
child: ListView(
reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 20),
children: messageBubbles),
);
});
}
}
class MessageBubble extends StatelessWidget {
final String text;
final String sender;
final bool isMe;
final Timestamp time; // add this
MessageBubble({this.text, this.sender, this.isMe, this.time}); //add the variable in this constructor
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment:
isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Text(
' $sender ${DateTime.fromMillisecondsSinceEpoch(time.seconds * 1000)}',// add this only if you want to show the time along with the email. If you dont want this then don't add this DateTime thing
style: TextStyle(color: Colors.black54, fontSize: 12),
),
Material(
color: isMe ? Colors.blueAccent : Colors.white,
borderRadius: isMe
? BorderRadius.only(
topLeft: Radius.circular(30),
bottomLeft: Radius.circular(30),
bottomRight: Radius.circular(30))
: BorderRadius.only(
topRight: Radius.circular(30),
bottomLeft: Radius.circular(30),
bottomRight: Radius.circular(30)),
elevation: 6,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15),
child: Text(
text,
style: TextStyle(
fontSize: 20, color: isMe ? Colors.white : Colors.black),
),
),
),
],
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
这是完整的工作解决方案。感谢 jquevedo 和 appbrewery。
\n\nimport \'package:flutter/cupertino.dart\';\nimport \'package:flutter/material.dart\';\nimport \'package:flash_chat/constants.dart\';\nimport \'package:firebase_auth/firebase_auth.dart\';\nimport \'package:cloud_firestore/cloud_firestore.dart\';\n\nfinal _firestore = Firestore.instance;\nFirebaseUser loggedInUser;\n\nclass ChatScreen extends StatefulWidget {\n static const String id = "chat_screen";\n\n @override\n _ChatScreenState createState() => _ChatScreenState();\n}\n\nclass _ChatScreenState extends State<ChatScreen> {\n final messageTextContoller = TextEditingController();\n final _auth = FirebaseAuth.instance;\n\n String messageText;\n\n @override\n void initState() {\n super.initState();\n getCurrentUser();\n }\n\n void getCurrentUser() async {\n try {\n final user = await _auth.currentUser();\n if (user != null) {\n loggedInUser = user;\n print(loggedInUser.email);\n }\n } catch (e) {\n print(e);\n }\n }\n\n void messagesStream() async {\n await for (var snapshot in _firestore.collection("messages").snapshots()) {\n for (var message in snapshot.documents) {\n print(message.data);\n }\n }\n }\n\n @override\n Widget build(BuildContext context) {\n return Scaffold(\n appBar: AppBar(\n leading: null,\n actions: <Widget>[\n IconButton(\n icon: Icon(Icons.close),\n onPressed: () {\n _auth.signOut();\n Navigator.pop(context);\n }),\n ],\n title: Text(\'\xe2\x9a\xa1\xef\xb8\x8fChat\'),\n backgroundColor: Colors.lightBlueAccent,\n ),\n body: SafeArea(\n child: Column(\n mainAxisAlignment: MainAxisAlignment.spaceBetween,\n crossAxisAlignment: CrossAxisAlignment.stretch,\n children: <Widget>[\n MessagesStream(),\n Container(\n decoration: kMessageContainerDecoration,\n child: Row(\n crossAxisAlignment: CrossAxisAlignment.center,\n children: <Widget>[\n Expanded(\n child: TextField(\n controller: messageTextContoller,\n onChanged: (value) {\n messageText = value;\n },\n decoration: kMessageTextFieldDecoration,\n ),\n ),\n FlatButton(\n onPressed: () {\n messageTextContoller.clear();\n _firestore.collection("messages").add({\n "text": messageText,\n "sender": loggedInUser.email,\n "time": DateTime.now()\n });\n },\n child: Text(\n \'Send\',\n style: kSendButtonTextStyle,\n ),\n ),\n ],\n ),\n ),\n ],\n ),\n ),\n );\n }\n}\n\nclass MessagesStream extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return StreamBuilder<QuerySnapshot>(\n stream: _firestore.collection("messages").snapshots(),\n // ignore: missing_return\n builder: (context, snapshot) {\n if (!snapshot.hasData) {\n return Center(\n child: CircularProgressIndicator(\n backgroundColor: Colors.lightBlueAccent,\n ),\n );\n }\n final messages = snapshot.data.documents;\n List<MessageBubble> messageBubbles = [];\n for (var message in messages) {\n final messageText = message.data[\'text\'];\n final messageSender = message.data["sender"];\n final messageTime = message.data["time"];\n final currentUsser = loggedInUser.email;\n final messageBubble = MessageBubble(\n sender: messageSender,\n text: messageText,\n time: messageTime,\n isMe: currentUsser == messageSender,\n );\n messageBubbles.add(messageBubble);\n messageBubbles.sort((a , b ) => b.time.compareTo(a.time));\n }\n return Expanded(\n child: ListView(\n reverse: true,\n padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20),\n children: messageBubbles,\n ),\n );\n },\n );\n }\n}\n\nclass MessageBubble extends StatelessWidget {\n final String sender;\n final String text;\n final Timestamp time;\n final bool isMe;\n\n MessageBubble({this.sender, this.text, this.isMe, this.time});\n\n @override\n Widget build(BuildContext context) {\n return Padding(\n padding: EdgeInsets.all(10.0),\n child: Column(\n crossAxisAlignment: isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,\n children: <Widget>[\n Text(\n "$sender ${time.toDate()}",\n style: TextStyle(\n color: Colors.grey,\n fontSize: 12,\n ),\n ),\n Material(\n borderRadius: isMe ? BorderRadius.only(\n topLeft: Radius.circular(30),\n bottomLeft: Radius.circular(30),\n bottomRight: Radius.circular(30),\n ) : BorderRadius.only(\n topRight: Radius.circular(30),\n bottomLeft: Radius.circular(30),\n bottomRight: Radius.circular(30),\n ),\n elevation: 5.0,\n color: isMe ? Colors.lightBlueAccent : Colors.purpleAccent,\n child: Padding(\n padding: EdgeInsets.symmetric(\n vertical: 10,\n horizontal: 20,\n ),\n child: Text(\n text,\n style: TextStyle(\n fontSize: 15,\n color: Colors.white,\n ),\n ),\n ),\n ),\n ],\n ),\n );\n }\n}\n\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
4667 次 |
| 最近记录: |