Skip to Content

How do you make a chat screen on flutter?

Flutter is an open-source UI software development kit created by Google. It is used to develop cross platform applications for Android, iOS, Linux, macOS, Windows, Google Fuchsia, and the web from a single codebase.

To make a chat screen in Flutter, you need to leverage the power of Flutter’s widget library to build a user interface that allows sending and receiving messages between users in real-time. This involves using widgets like TextField, ListView, StreamBuilder etc. You also need to integrate a chat backend like Firebase to store and sync chat messages across devices.

Here are the key requirements for building a chat screen in Flutter:

Set up Firebase

Flutter apps can integrate with Firebase services like Firestore database and authentication to enable chat functionalities. You need to:

  • Create a Firebase project
  • Register the app with Firebase
  • Add Firebase SDKs like firebase_core, cloud_firestore and firebase_auth
  • Initialize Firebase in the app

This sets up the realtime database and authentication backend for the chat.

Design the chat UI

The chat UI can be designed using Flutter widgets like:

  • AppBar for the app bar section
  • ListView builder to display chat messages
  • TextField to type new messages
  • Buttons to send messages

The UI should also include user profile avatars, date separators, ability to send text, images, videos etc.

Implement authentication

Use Firebase authentication to let users sign in anonymously or with a Google/Facebook account before accessing the chat.

This identifies each user with a unique ID to track their messages.

Store and retrieve messages

When sending a message, write it to Cloud Firestore along with sender ID, timestamp etc.

Use StreamBuilder to listen to changes in realtime and display new messages as they arrive.

Add additional features

Other features you can add include:

  • Typing indicators when someone is typing
  • Read receipts when messages are read
  • Online presence indicators
  • Support for attachments and reactions
  • Threading replies

This enhances the chat experience.

Step 1 – Set up Firebase

To enable realtime messaging capabilities, we need to integrate Firebase with our Flutter app. Here are the steps:

  1. Go to https://firebase.google.com and create a new Firebase project
  2. Register your Flutter app with the project by adding an Android and iOS app
  3. Add the firebase_core plugin to pubspec.yaml:
    dependencies:
      flutter:
        sdk: flutter
      firebase_core: "^1.17.1" 
    
  4. Import firebase_core in your code:
    import 'package:firebase_core/firebase_core.dart';
    
  5. Initialize Firebase by calling initializeApp() in your app’s main function:
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp();
      runApp(MyApp());
    }
    

This sets up the basic Firebase integration. We’ll add more capabilities like Firestore and Auth later.

Step 2 – Design the Chat UI

Our chat UI should have a list of messages, a text field to type new messages and a send button.

Let’s break it down into widgets:

ListView

This displays the list of chat messages. We can use a ListView.builder constructor to build the list items on demand.

ListView.builder(
  itemCount: messages.length,
  itemBuilder: (context, index) {
    return ChatMessageTile(message: messages[index]); 
  }
)  

ChatMessageTile is a custom widget to display each message.

Text Field

We use a TextField widget for the user to type a new chat message.

TextField(
  decoration: InputDecoration(hintText: "Type message"),
  controller: messageController,
)

We store the typed message in a TextEditingController called messageController.

Send Button

A simple ElevatedButton allows the user to send the message.

ElevatedButton(
  child: Text("Send"), 
  onPressed: () {
    // send message
  }
)

When clicked, it will take the text from messageController and send it.

AppBar

An AppBar shows the chat title and actions like user’s profile picture.

AppBar(
  title: Text("Chat Title"),
  actions: [
    IconButton(icon: Icon(Icons.person), onPressed: () {})
  ],
)

This completes the UI. Next we’ll add the backend logic.

Step 3 – Implement Firebase Authentication

We want users to sign-in before accessing the chat. Firebase Auth lets us authenticate users easily.

Add the firebase_auth plugin

dependencies:
  flutter:
    sdk: flutter

  firebase_core: ^1.17.1
  firebase_auth: ^3.3.19  

Import the plugin

import 'package:firebase_auth/firebase_auth.dart';

Check authentication state

We can check if a user is signed in with:

FirebaseAuth.instance.authStateChanges()

This Stream will emit the user if they are signed in or null if signed out.

Sign in anonymously

Allow users to sign in anonymously without needing an account:

try {
  UserCredential user = await FirebaseAuth.instance.signInAnonymously();
} catch (e) {
  print(e); 
}

The user credential contains the FirebaseUser with a unique ID.

Sign out

FirebaseAuth.instance.signOut();

Signs out the current user.

This implements anonymous authentication for our chat app. We can also add Google, Facebook etc sign-in options.

Step 4 – Store and Retrieve Messages with Firestore

To sync messages across devices, we need to store them in Firestore’s cloud database.

Add cloud_firestore plugin

dependencies:

  firebase_core: ^1.17.1
  cloud_firestore: ^3.1.17 

Create ChatMessage model

We need a model class to represent chat messages:

class ChatMessage {
  String id;
  String text;
  User sender;
  Timestamp time;

  ChatMessage({this.id, this.text, this.sender, this.time});
}

It contains the message text, sender details, timestamp etc.

Send message

When the user sends a message, add it to Firestore:

FirebaseFirestore.instance.collection('messages').add({
  'text': messageText,
  'sender': loggedInUser.email,
  'timestamp': Timestamp.now()
});

This adds the message to the ‘messages’ collection with a unique auto-generated ID.

Receive messages

Use StreamBuilder to listen for changes and load new messages:

StreamBuilder(
  stream: FirebaseFirestore.instance
      .collection('messages')
      .orderBy('timestamp', descending: true)
      .snapshots(),
  builder: (context, snapshot) {
    if (!snapshot.hasData) {
      return Center(
        child: CircularProgressIndicator(),
      );
    }

    return ListView(
      children: snapshot.data.docs.map((doc) {
        return ChatMessageTile(
          message: ChatMessage.fromDoc(doc),
        );
      }).toList(),
    );
  }
)

ChatMessage.fromDoc() converts the Firestore document snapshot to our ChatMessage model.

Now our app can send, receive and display chat messages in realtime with Firestore!

Step 5 – Add Additional Features

Our basic chat UI and backend is complete. Let’s enhance the experience with some common chat features.

Typing Indicators

Show “User is typing” when the other user is composing a message.

– Listen for changes to a ‘typing’ node on Firestore
– Display the indicator if set to true

StreamBuilder(
  stream: FirebaseFirestore.instance
    .doc('/typing/${otherUserId}')
    .snapshots(),
  builder: (context, snapshot) {
    if (snapshot.data == true) {
      return Text("$otherUserName is typing...");
    } else {
      return SizedBox(); 
    }
  }  
)

Read Receipts

Mark messages as read once the user views them.

– Add boolean ‘read’ field to ChatMessage
– Update it to true when user reads the message

 
ChatMessage.fromDoc(doc) {
  read: doc['read'] ?? false,
}

// mark as read
FirebaseFirestore.instance
  .doc('/messages/${messageId}')
  .update({'read': true});

Presence Indicators

Show “Online” or “Offline” based on user’s connectivity.

– Listen on Firestore for user’s online status
– Update status on app foreground/background

StreamBuilder(
  stream: FirebaseFirestore.instance
    .doc('/status/${otherUserId}')
    .snapshots(),
  builder: (context, snapshot) {
    bool isOnline = snapshot.data['isOnline'] ?? false;
    
    if (isOnline) {
      return Text("$otherUserName is online");
    } else {
      return Text("$otherUserName is offline");   
    }
}); 

This covers some common enhancements to build a full-featured chat experience. Flutter coupled with Firebase provides a powerful platform for building messaging apps.

Conclusion

Building a chat screen is easy with Flutter by leveraging its powerful UI framework and integrating services like Firebase for the backend.

The key steps are:

  • Set up Firebase for authentication and realtime data sync
  • Design the UI using Flutter widgets like ListView, TextField etc
  • Add authentication for users to sign-in
  • Integrate Firestore to store and retrieve chat messages
  • Add features like typing indicators, read receipts etc

Flutter wraps these complex integrations into simple declarative widgets so you can focus on building the app UI and logic.

Combined with Firebase’s scalable infrastructure for messaging and storage, you can quickly build secure and full-featured chat applications on both iOS and Android with a single Dart/Flutter codebase.

The powerful Flutter framework coupled with Firebase backend enables developers to build cross-platform chat apps in record time with a rich set of features. So go ahead and use these tools to create the next great messaging app!