firebase - 如何在 Flutter 中显示最后的消息
问题描述
我有我正在做的这个项目。这是一个聊天应用程序。我已经能够处理大部分功能,但需要一些帮助。我使用 firebase 作为后端,所有数据都从 firestore 存储和检索,以在聊天中显示消息。我注意到在打开聊天时我没有自动看到最后一条消息,就像它在 whatsapp 或其他聊天应用程序上正常显示的方式一样。例如,如果我输入一条新消息,我希望它是页面底部显示的最后一件事。请帮我检查一下。这是我的代码:
import 'package:chat/constants.dart';
import 'package:chat/utilities/constants.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:emoji_picker/emoji_picker.dart';
import 'package:flutter/material.dart';
import 'package:chat/models/auth.dart';
import 'package:chat/models/message.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class ChatScreen extends StatefulWidget {
final AuthImplementation auth;
final VoidCallback signedOut;
ChatScreen({
this.auth,
this.signedOut,
});
@override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
bool show = false;
FocusNode focusNode = FocusNode();
final Firestore _firestore = Firestore.instance;
TextEditingController messageController = TextEditingController();
ScrollController scrollController = ScrollController();
String userName;
@override
void initState() {
super.initState();
widget.auth.getCurrentUserEmail().then((email) {
setState(() {
final String userEmail = email;
final endIndex = userEmail.indexOf("@");
userName = userEmail.substring(0, endIndex);
focusNode.addListener(() {
if (focusNode.hasFocus) {
setState(() {
show = false;
});
}
});
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: new Container(
padding: new EdgeInsets.all(8.0),
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage("assets/images/social-logo.png"),
fit: BoxFit.fill),
color: Colors.white,
borderRadius: new BorderRadius.all(new Radius.circular(80.0)),
border: new Border.all(
color: Colors.white,
width: 1.0,
),
),
),
title: Text("One Gov FX Signal Room",
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.bold,
fontFamily: 'Spartan',
)),
backgroundColor: kPrimaryColor,
actions: <Widget>[
IconButton(
icon: FaIcon(FontAwesomeIcons.signOutAlt),
color: Colors.white,
onPressed: logOut),
],
),
backgroundColor: antiFlashWhite,
body: WillPopScope(
child: Column(
children: <Widget>[
Container(
color: Colors.white,
padding:
EdgeInsets.only(left: 10, right: 0, bottom: 10, top: 10),
child: Row(
children: [
CircleAvatar(
backgroundColor: Colors.white,
backgroundImage:
AssetImage("assets/images/social-logo.png"),
),
SizedBox(
width: 50,
),
Flexible(
child: Column(children: const <Widget>[
Text('Message From the Admins'),
Text(
'Keep your messages polite and do not abuse the channel. Try to keep your discussions within the community guidelines'),
]),
)
],
),
),
Expanded(
child: Container(
//margin: EdgeInsets.symmetric(horizontal: 5),
child: StreamBuilder<QuerySnapshot>(
stream: _firestore
.collection("messages")
.orderBy(
"timestamp",
)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(
child: CircularProgressIndicator(
backgroundColor: kPrimaryColor,
),
);
List<DocumentSnapshot> docs = snapshot.data.documents;
List<Widget> messages = docs
.map((doc) => Message(
user: doc.data['user'],
text: doc.data['text'],
timestamp: doc.data['timestamp'],
mine: userName == doc.data['user'],
))
.toList();
return ListView(
controller: scrollController,
children: messages,
);
}),
),
),
Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
children: <Widget>[
IconButton(
icon: FaIcon(
FontAwesomeIcons.smile,
color: kPrimaryColor,
),
onPressed: () {
focusNode.unfocus();
focusNode.canRequestFocus = false;
setState(() {
show = !show;
});
},
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(10),
child: TextField(
focusNode: focusNode,
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 15,
),
onSubmitted: (value) => sendChat(),
controller: messageController,
scrollController: scrollController,
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.newline,
maxLines: null,
cursorColor: kPrimaryColor,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20)),
filled: true,
hintText: "Say Something. Be Nice...",
hintStyle: TextStyle(
fontFamily: 'Montserrat', fontSize: 12),
),
),
),
),
IconButton(
icon: FaIcon(
FontAwesomeIcons.file,
color: kPrimaryColor,
),
onPressed: () {
showModalBottomSheet(
backgroundColor: Colors.transparent,
context: context,
builder: (builder) => bottomsheet());
},
),
IconButton(
icon: FaIcon(
FontAwesomeIcons.paperPlane,
color: kPrimaryColor,
),
onPressed: sendChat,
),
],
),
show ? emojiSelect() : Container(),
],
),
),
],
),
onWillPop: () {
if (show) {
setState(() {
show = false;
});
} else {
Navigator.pop(context);
}
return Future.value(false);
}),
);
}
void logOut() async {
try {
await widget.auth.signOut();
widget.signedOut();
} catch (e) {
print("error :" + e.toString());
}
}
Future<void> sendChat() async {
if (messageController.text.length > 0) {
await _firestore.collection("messages").add({
'user': userName,
'text': messageController.text,
'timestamp': FieldValue.serverTimestamp(),
});
messageController.clear();
scrollController.animateTo(scrollController.position.maxScrollExtent,
duration: Duration(milliseconds: 300), curve: Curves.easeOut);
}
}
Widget bottomsheet() {
return Container(
height: 120,
width: MediaQuery.of(context).size.width,
child: Card(
margin: EdgeInsets.all(0),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
child: iconcreation(
Icons.analytics,
Colors.black,
"Analysis",
)),
SizedBox(
width: 40,
),
iconcreation(Icons.report, Colors.black, "Report User"),
SizedBox(
width: 40,
),
iconcreation(Icons.link, Colors.black, "Link")
],
),
),
),
);
}
Widget iconcreation(IconData icon, Color color, String text) {
return InkWell(
onTap: () {},
child: Column(
children: [
CircleAvatar(
backgroundColor: color,
radius: 30,
child: Icon(
icon,
size: 29,
color: Colors.white,
),
),
SizedBox(height: 5),
Text(text),
],
),
);
}
Widget emojiSelect() {
return EmojiPicker(
rows: 4,
columns: 7,
onEmojiSelected: (emoji, category) {
print(emoji);
setState(() {
messageController.text = messageController.text + emoji.emoji;
});
});
}
}
这是应用程序的示例图像: 应用程序的 屏幕截图
解决方案
descending: true
在时间戳之后添加。
喜欢Expanded( child: Container( //margin: EdgeInsets.symmetric(horizontal: 5), child: StreamBuilder<QuerySnapshot>( stream: _firestore .collection("messages") .orderBy( "timestamp", descending: true ) .snapshots(), builder: (context, snapshot) { if (!snapshot.hasData) return Center( child: CircularProgressIndicator( backgroundColor: kPrimaryColor, ), );
推荐阅读
- automation - 赛普拉斯:如何上传压缩的 tar 文件
- json - 使用 jolt 条件更新 json 属性
- python - 尝试将文件复制到启动时权限被拒绝 - Python 和 auto-py-to-exe
- redirect - 如何从适合特定格式的 url 中删除关键字?
- react-native - 如何使 ListHeaderComponent 的一部分粘在 React Native FlatList 上
- javascript - 使用传单搜索显示两次标记
- tableau-api - Tableau 巨大的 if else 条件计算导致请求大小超过解析器限制 1048500 字节
- azure - Azure App Service VNET 集成和网络优化
- java - 减少 Spring Boot 中的 JSON 响应
- python - pygame.display.update(); pygame.error:视频系统未初始化