Чтобы создать приложение для чата 1–1 во Flutter с помощью Cloud Firestore, вы можете выполнить следующие действия:
- Создайте новый проект Flutter в предпочитаемой вами среде разработки.
- Настройте проект Firebase и подключите его к приложению Flutter, следуя инструкциям в Документации Firebase.
- В консоли Firebase создайте новую базу данных Cloud Firestore и установите для нее правила безопасности, чтобы разрешить доступ для чтения и записи для пользователей, прошедших проверку подлинности.
- В своем приложении Flutter установите пакет
cloud_firestore
. - Реализуйте поток аутентификации в своем приложении с помощью службы аутентификации Firebase. Вы можете использовать адрес электронной почты/пароль, номер телефона или любой другой поддерживаемый поставщик удостоверений.
- Создайте экран чата в своем приложении, где пользователи могут отправлять и получать сообщения. Вы можете использовать виджет
ListView
для отображения сообщений в прокручиваемом списке. - Используйте метод Cloud Firestore
add()
для сохранения сообщений в базе данных. Вы можете хранить каждое сообщение как документ в коллекции с полями для отправителя, получателя, текста сообщения и метки времени. - Используйте прослушиватель Cloud Firestore
snapshot
для прослушивания обновлений коллекции сообщений в режиме реального времени и обновления экрана чата при получении новых сообщений.
Это общий обзор того, как вы можете создать приложение для чата 1-1 во Flutter с помощью Cloud Firestore. Дайте мне знать, если у вас есть какие-либо вопросы или вам нужна дополнительная информация.
Это пример исходного кода для этого приложения:
import 'dart:math'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(const MyApp()); } int user = Random().nextInt(3000); class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData(primaryColor: Colors.teal), title: 'Chat App', home: const ChatScreen(), ); } }
Экран чата. дротик
class ChatScreen extends StatefulWidget { const ChatScreen({Key? key}) : super(key: key); @override _ChatScreenState createState() => _ChatScreenState(); } class _ChatScreenState extends State<ChatScreen> { final _firestore = FirebaseFirestore.instance; final _textController = TextEditingController(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Row( children: const [ CircleAvatar( radius: 22, backgroundImage: NetworkImage( 'https://user-images.githubusercontent.com/89972827/208123817-524df66c-fcc6-4a29-8c27-cdeb3c989e41.png', ), ), SizedBox( width: 10, ), Text('Chat'), ], ), actions: [ IconButton( onPressed: () {}, icon: const Icon(Icons.videocam), ), IconButton( onPressed: () {}, icon: const Icon(Icons.phone), ), IconButton( onPressed: () {}, icon: const Icon(Icons.more_vert), ), ], backgroundColor: Colors.grey.shade800, ), backgroundColor: Colors.grey.shade800, body: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const MessageStream(), Container( padding: const EdgeInsets.all(5), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: Container( decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(50)), color: Colors.grey.shade700, ), child: TextField( controller: _textController, cursorColor: Colors.teal, style: const TextStyle(color: Colors.white), decoration: const InputDecoration( contentPadding: EdgeInsets.symmetric( vertical: 10.0, horizontal: 20.0, ), hintText: 'Message', hintStyle: TextStyle(color: Colors.white), border: InputBorder.none, ), ), ), ), ElevatedButton( onPressed: () async { if (_textController.text.trim() != '') { await _firestore.collection('messages').add({ 'text': _textController.text, 'sender': '$user', 'dt': DateTime.now(), }); _textController.clear(); } }, style: ElevatedButton.styleFrom( minimumSize: const Size(45, 45), shape: const CircleBorder(), primary: Colors.teal, ), child: const Icon( Icons.send, size: 25, ), ), ], ), ), ], ), ); } }
Поток сообщений
class MessageStream extends StatelessWidget { const MessageStream({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return StreamBuilder<QuerySnapshot>( stream: FirebaseFirestore.instance .collection('messages') .orderBy( 'dt', descending: true, ) .snapshots(), builder: (context, snapshot) { if (!snapshot.hasData) { return const Center( child: CircularProgressIndicator( backgroundColor: Colors.teal, ), ); } final messages = snapshot.data!.docs; List<MessageBubble> messageBubbles = []; for (var message in messages) { final messageText = (message.data()! as Map)['text']; final messageSender = (message.data()! as Map)['sender']; String currentUser = user.toString(); final messageBubble = MessageBubble( sender: messageSender, text: messageText, isMe: currentUser == messageSender, ); messageBubbles.add(messageBubble); } return Expanded( child: ListView( reverse: true, padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0), children: messageBubbles, ), ); }, ); } }
Пузырь сообщений
class MessageBubble extends StatelessWidget { const MessageBubble({ Key? key, required this.sender, required this.text, required this.isMe, }) : super(key: key); final String sender; final String text; final bool isMe; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(10.0), child: Column( crossAxisAlignment: isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start, children: [ Material( borderRadius: isMe ? const BorderRadius.only( topLeft: Radius.circular(30.0), bottomLeft: Radius.circular(30.0), bottomRight: Radius.circular(30.0), ) : const BorderRadius.only( topRight: Radius.circular(30.0), bottomLeft: Radius.circular(30.0), bottomRight: Radius.circular(30.0), ), color: isMe ? Colors.teal : Colors.grey.shade700, child: Padding( padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( sender, style: TextStyle( fontSize: 12.0, fontWeight: FontWeight.bold, color: Colors .primaries[Random().nextInt(Colors.primaries.length)], ), ), const SizedBox( height: 5, ), Text( text, style: TextStyle( color: isMe ? Colors.white : Colors.white, fontSize: 15.0, ), ), ], ), ), ), ], ), ); } }
Спасибо Оставьте хлопок и комментарий, если вам понравилась эта статья.