Tutorials

Building a Chat App UI in Flutter: A Complete Guide with Code

Building a Chat App UI in Flutter: A Complete Guide with Code

Building chat applications has become one of the most popular ways to learn app development, as they combine user interface design with real-time interaction. Flutter, Google’s open-source UI toolkit, makes this process both beginner-friendly and powerful. With its “write once, run anywhere” approach, you can create beautiful apps for Android, iOS, web, and desktop from a single codebase. Its widget-based design system allows developers to craft responsive, attractive interfaces with minimal effort, making it an excellent choice for building chat applications where layout and usability matter most.

In this guide, we will walk step by step through the process of creating a simple chat app interface. You’ll learn how to design a chat screen, build message bubbles for users and others, and add an input box with send functionality. To keep things engaging, we’ll even simulate automatic replies, so the app feels alive even without a backend connection. This tutorial is tailored for beginners, so you don’t need prior experience with advanced Flutter concepts—just a basic understanding of Dart and the enthusiasm to learn. By the end, you’ll have a working chat UI foundation that you can later extend with advanced features like Firebase integration or local storage.

Flutter Chat App UI Project Setup

Before you start building the chat UI, you need to set up your Flutter environment. Begin by downloading and installing the Flutter SDK, then add its bin folder to your system PATH. Run flutter doctor to make sure everything is correctly set up and ready for development. Next, create a new project with flutter create chat_app_ui and open it in your IDE. Focus on the lib folder and the main.dart file, as this is where you’ll write most of your code. Having everything properly set up first will make building and testing your chat app much smoother and more enjoyable.

Install Flutter and Set Up the Environment

To get started, make sure Flutter is installed on your computer.

  • Download Flutter SDK: Visit the official Flutter website and download the stable version for your operating system (Windows, macOS, or Linux).
  • Extract and Add to Path: Unzip the Flutter folder and add its bin directory to your system’s PATH environment variable.
  • Check Installation: Open your terminal or command prompt and run: flutter doctor This command checks your environment and displays what tools need to be configured (e.g., Android Studio, Xcode, or VS Code plugins).

Create a New Flutter Project

  • Once Flutter is ready, let’s create our chat app project:
flutter create chat_app_ui
cd chat_app_ui
  • This command generates all the files and folders required for your project.
  • You can now open the project in VS Code or Android Studio to begin coding.

Understanding the Project Structure

A Flutter project comes with several folders and files. For our chat app, you mainly need to focus on the following:

  • lib/: This is the most important folder. It contains your Dart code. The entry point is main.dart.
  • pubspec.yaml: This file manages app dependencies, assets, and package versions.
  • android/ and ios/: These contain platform-specific files. You usually won’t need to touch them as a beginner.
  • test/: For writing unit and widget tests (optional at this stage).

For our simple chat app UI, all the main logic and design will be inside lib/main.dart.

Running the Starter App

To confirm everything works:

  • Connect a device or start an emulator.
  • Run:
flutter run
  • You should see the default Flutter counter app. This means your environment is ready to build the chat app UI.

Step-by-Step Guide to Building a Chat App UI in Flutter

Flutter’s cross-platform framework allows you to build a single chat UI that works seamlessly on Android, iOS, web, and desktop. Our chat screen consists of three main parts: the app structure, message list, and input area. We’ll start by setting up the overall screen layout using Scaffold and AppBar. Next, we’ll create a scrollable list to display messages dynamically. Finally, we’ll add an input area with a TextField and send button for user interaction. Following these steps will give you a functional chat UI foundation ready for further enhancements.

Flutter Chat App UI: App Structure Explained

We start by setting up the skeleton of our screen.

Scaffold(
  appBar: AppBar(
    title: const Text("Chat App"),
    backgroundColor: Colors.blueAccent,
  ),
  body: Column(
    children: [
      // Messages will go here
      // Input box will go here
    ],
  ),
);

Key points:

  • AppBar → shows the title at the top.
  • Column → lets us stack chat messages (top) and input field (bottom).

Designing Chat Bubbles in Flutter Chat App UI

We display messages in a scrollable list.

Expanded(
  child: ListView.builder(
    itemCount: messages.length,
    itemBuilder: (context, index) {
      final msg = messages[index];
      return Align(
        alignment: msg["isUser"]
            ? Alignment.centerRight
            : Alignment.centerLeft,
        child: Container(
          margin: const EdgeInsets.symmetric(vertical: 5),
          padding: const EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: msg["isUser"] ? Colors.blue[200] : Colors.grey[300],
            borderRadius: BorderRadius.circular(12),
          ),
          child: Text(msg["text"]),
        ),
      );
    },
  ),
),

How it works:

  • ListView.builder → dynamically builds messages.
  • User → right-aligned blue bubble.
  • Other → left-aligned grey bubble.

Input Area (Type & Send)

At the bottom, we add the message box and send button.

Row(
  children: [
    Expanded(
      child: TextField(
        controller: _controller,
        decoration: InputDecoration(
          hintText: "Type a message...",
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(20),
          ),
        ),
      ),
    ),
    IconButton(
      icon: const Icon(Icons.send, color: Colors.blueAccent),
      onPressed: _sendMessage,
    ),
  ],
),

Highlights:

  • TextField → user types here.
  • Expanded → makes input stretch across the row.
  • IconButton → sends the message.

Adding Functionality to the Flutter Chat App UI

So far, we have a static chat UI: an app bar, a scrollable list for messages, and an input box at the bottom. But the app doesn’t actually do anything yet—typing in the text field won’t add new messages, and nothing happens when we tap the send button.

This section will transform our simple layout into an interactive chat experience. You’ll learn how to:

  • Store and update chat messages.
  • Send a new message and display it instantly.
  • Clear the input field after sending.
  • Simulate automatic replies from a bot or “friend.”

By the end of this section, your app will feel like a real chat application instead of just a static interface.


How to Store Messages in Flutter Chat App UI

Every chat app needs a way to store messages temporarily in memory. Since this is a beginner project, we don’t need a database yet—we can simply use a list in Dart.

We’ll keep each message as a Map containing:

  • "text" → the actual message string.
  • "isUser" → a Boolean value (true or false) that indicates whether the message came from the user or someone else.

Example:

final List<Map<String, dynamic>> _messages = [];

Now, whenever the user types and sends a message, we’ll add a new entry like this:

_messages.add({
  "text": "Hello!",
  "isUser": true,
});

And for an automatic reply, we might add:

_messages.add({
  "text": "Got it, thanks!",
  "isUser": false,
});

This way, our app can differentiate between user and bot messages and style them accordingly (blue bubble for user, grey bubble for others).


Sending a Message

Next, we need a way to let the user send messages. Remember our input row? It contains a TextField and a Send button. We’ll connect that button to a function called _sendMessage().

Here’s the code:

void _sendMessage() {
  if (_controller.text.trim().isEmpty) return; // Prevent empty messages

  setState(() {
    _messages.add({
      "text": _controller.text,
      "isUser": true,
    });
  });

  _controller.clear(); // Clear the input field
}

How it works:

  • We check if the text field is empty (so pressing send with no text does nothing).
  • setState → tells Flutter that our data has changed, and it should rebuild the UI with the updated list.
  • We add a new map containing the text and isUser: true.
  • Finally, we clear the input so the user can type again.

At this point, try running the app. You’ll see your messages appear instantly in the chat window!


Clearing the Text Field

Without clearing the text field, the old message would still remain after pressing send, which feels unnatural. That’s why we use:

_controller.clear();

This resets the text box to empty, ready for the next message. It’s a small but essential detail in making the app feel professional.


Adding a Bot Reply to Flutter Chat App UI

Most chat apps have two participants. To make ours feel more real, let’s simulate a simple bot reply.

We can use Dart’s Future.delayed function, which lets us run code after a short delay.

Future.delayed(const Duration(seconds: 1), () {
  setState(() {
    _messages.add({
      "text": "Got it! '${_messages.last["text"]}'",
      "isUser": false,
    });
  });
});

What this does:

  • Waits 1 second after the user sends a message.
  • Adds a new message from the “bot” (with isUser: false).
  • Rebuilds the chat so the reply shows up.

This trick makes the chat feel interactive, even though it’s not connected to a real server yet.


Final Code

Now that we’ve added functionality, let’s look at the full working code. This includes the app structure, message list, input field, and the automatic bot reply. You can paste this into your lib/main.dart file and run it on your device or emulator. Once running, you’ll be able to type messages, send them, and see the simulated responses appear instantly. This final code provides a complete, interactive chat UI that serves as a solid foundation for further enhancements like Firebase integration, dark mode, or avatars.

import 'package:flutter/material.dart';

void main() {
  runApp(const ChatApp());
}

class ChatApp extends StatelessWidget {
  const ChatApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Chat App UI',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const ChatScreen(),
    );
  }
}

class ChatScreen extends StatefulWidget {
  const ChatScreen({super.key});

  @override
  State<ChatScreen> createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  final List<Map<String, dynamic>> _messages = []; // Store messages
  final TextEditingController _controller = TextEditingController();

  void _sendMessage() {
    if (_controller.text.trim().isEmpty) return;
    setState(() {
      _messages.add({
        "text": _controller.text,
        "isUser": true,
      });
    });
    _controller.clear();

    // Fake bot reply
    Future.delayed(const Duration(seconds: 1), () {
      setState(() {
        _messages.add({
          "text": "Got it! '${_messages.last["text"]}'",
          "isUser": false,
        });
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Chat App"),
        backgroundColor: Colors.blueAccent,
      ),
      body: Column(
        children: [
          // Message List
          Expanded(
            child: ListView.builder(
              padding: const EdgeInsets.all(10),
              itemCount: _messages.length,
              itemBuilder: (context, index) {
                final message = _messages[index];
                return Align(
                  alignment: message["isUser"]
                      ? Alignment.centerRight
                      : Alignment.centerLeft,
                  child: Container(
                    margin: const EdgeInsets.symmetric(vertical: 5),
                    padding: const EdgeInsets.all(12),
                    decoration: BoxDecoration(
                      color: message["isUser"]
                          ? Colors.blue[200]
                          : Colors.grey[300],
                      borderRadius: BorderRadius.circular(12),
                    ),
                    child: Text(
                      message["text"],
                      style: const TextStyle(fontSize: 16),
                    ),
                  ),
                );
              },
            ),
          ),

          // Input Field
          SafeArea(
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _controller,
                    decoration: InputDecoration(
                      hintText: "Type a message...",
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(20),
                      ),
                      contentPadding:
                          const EdgeInsets.symmetric(horizontal: 15),
                    ),
                  ),
                ),
                IconButton(
                  icon: const Icon(Icons.send, color: Colors.blueAccent),
                  onPressed: _sendMessage,
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

Running the App:

  • Type something into the input box.
  • Press the send button → your message appears in a bubble.
  • After 1 second → the “bot” replies with an automatic response.

Improving and Scaling Your Flutter Chat App UI

Right now, our app is a basic prototype. But you can easily extend it into a scalable architecture for something more powerful. You can add avatars or profile pictures to make conversations more personal. Timestamps can be displayed to show when each message was sent or received. Integrating Firebase allows real-time messaging across devices, while local storage ensures chat history persists offline. Dark mode improves usability in low-light environments, and design enhancements like animated bubbles, shadows, and swipe gestures make the app more engaging. These improvements lay the foundation for a scalable, interactive, and future-ready chat app.

1. Add Avatars / Profile Pictures

  • Show a small profile image next to each message bubble.
  • Use CircleAvatar widget inside the message row.
  • Optionally, display user initials if no image is available.
  • Allow users to tap the avatar to view a larger profile or status.
  • Differentiate between sender and receiver avatars with a border color.
  • Support animated avatars (like a typing indicator or GIF).

2. Add Timestamps

  • Store a "time" value with each message.
  • Display it below or beside the bubble (e.g., 10:45 PM).
  • Format timestamps based on the device’s locale.
  • Show “Today / Yesterday” labels for older messages.
  • Optionally display “Seen” or “Delivered” status with the timestamp.
  • Highlight new messages with a timestamp divider (e.g., 5 min gap).

3. Connect to Firebase

  • Use Cloud Firestore to save and retrieve messages in real-time.
  • This allows two users on different devices to chat with each other live.
  • Use Firebase Authentication to identify users securely.
  • Implement offline persistence so messages sync when connection resumes.
  • Use Firebase Storage for sending images, videos, or files.
  • Set up Firestore rules to ensure privacy and security for each user’s messages.

4. Save Chat History Locally

  • Use Hive or SQLite to store conversations on the device.
  • So even if you close the app, messages remain.
  • Sync local storage with Firebase for offline and online continuity.
  • Allow users to search messages locally.
  • Optionally delete messages after a certain time or manually.
  • Backup and restore local chat history using cloud or device storage.

5. Add Dark Mode

  • Use ThemeData.dark() for dark themes.
  • Switch between light/dark modes with a button.
  • Animate the theme transition for smooth switching.
  • Remember the user’s theme preference using shared preferences.
  • Adjust avatar and bubble colors for readability in both modes.
  • Support dynamic system theme changes automatically.

6. Improve Design

  • Add shadows, gradients, or rounded corners for stylish bubbles.
  • Animate messages appearing with AnimatedList.
  • Use custom fonts or text styles for unique chat appearance.
  • Add emoji reactions to messages.
  • Implement swipe gestures (like reply, delete, forward).
  • Show typing indicators or animated loading placeholders for incoming messages.

Conclusion

Building a chat application UI in Flutter is not only a great beginner-friendly project but also a practical step toward mastering mobile app development. By walking through the process of designing a clean and functional interface, you gain a deeper understanding of Flutter’s widget system and its ability to create flexible layouts. From constructing message bubbles to designing an input field, every component shows how Flutter encourages modular design. Even though the app we created does not yet connect to a real-time backend, it lays the foundation for a future-ready chat experience.

What you’ve achieved here is more than just a mock-up; it is a functional user interface where messages can be typed, sent, and displayed in an intuitive flow. Such a project strengthens your confidence in Flutter and helps you visualize how professional apps like WhatsApp, Messenger, or Telegram are structured at their core.

The journey does not end here. This beginner-friendly app can easily be extended with more advanced features such as Firebase integration for real-time messaging, user authentication, message persistence, media sharing, and push notifications. Flutter’s cross-platform capability ensures that the effort you put in benefits both Android and iOS, making it highly efficient.

As you continue to experiment, you can add themes, improve UI with animations, and explore state management tools like Provider, Riverpod, or Bloc to handle data flow better. Remember, every great application starts small, and your chat UI is the first step in building something scalable and impactful.

With consistency, practice, and curiosity, you’ll be ready to transform this simple project into a professional-grade chat app. The skills you’ve gained in this guide will serve as a solid foundation for your future Flutter projects—whether personal, academic, or professional.


.

You may also like...