Android Chat Tutorial: Building a Messaging UI


Get Started!

Sign up for a full-featured 30 day free trial. No credit card required.

Free Trial

Despite their growing prevalence, chat and messaging apps continue to be tedious to implement. Official documentation is non-existent, while unofficial tutorials are scarce and generally outdated.

Colorful chat bubbles filled with text, images, even playable media–how do they do it? The answer is surprisingly simple: RecyclerViews, coupled with the ViewHolder pattern.

This tutorial walks you through the steps required to build a quality messaging UI.

Setting up the Activity

In this tutorial, we’ll create a dedicated activity to host our messages. Let’s call it MessageListActivity. The primary component in this activity is a RecyclerView that fills most of the screen. To keep ahead of the curve, a ConstraintLayout will be used as the root ViewGroup.

In addition to displaying message history, chat UIs typically allow the user to send messages through a chatbox. We’ll position this chatbox at the bottom of the screen using constraints. This will anchor it to the soft input keyboard that pops up when the user types.


This creates two elements:

  1.  A flexible chatbox that expands according to the length of the message being typed
  2.  A RecyclerView that designates the remaining space to past messages

It will look like the following image:

Creating a list item for each message

Use a separate XML file to define the layout of each item (i.e. message) for ListViews and RecyclerViews. It is common practice for each message to contain the sender’s name, their profile image, and a timestamp.

Since the chat bubble’s alignment typically indicates the message’s owner, it could be redundant to display the sender’s profile image and name for every message. In the above image, for example, the right-aligned chat bubble indicates that it belongs to the sender, so we need not include the image or name. Most chat clients choose to discard these components altogether. We will do the same by creating two different ViewHolder‘s:

  1. SentMessageHolder for messages that “I” have sent
  2. ReceivedMessageHolder for messages sent by others

To create the above image, we must first create a chat bubble in an XML file. Once again, this is surprisingly simple:

  1. Set a rounded rectangle as the background for TextView
  2. Adjust the paddings
  3. Align the text


Voila! We now have a handsome chat bubble housing the message.

You can appropriately position the other TextViews using constraints. Be sure to create two more constraints before moving on:

  1. Be sure to set your root layout’s height to wrap_content, so it can accommodate messages containing a single line and messages containing more than a single line
  2. Set the message body’s max_width to an appropriate threshold. Without this constraint, the chat bubble will fill the entire screen’s width, and will look clumsy.

Now let’s apply this model to both the received and sent messages.

Received Messages


This produces the following image for received messages.

Sent Messages

For sent messages, align the chat bubble to the right, and remove the sender’s name and profile image.


Creating an Adapter for the RecyclerView

Populate the RecyclerView with the above XML items by creating an adapter that extends RecyclerView.Adapter. This adapter will accomplish three things:

  1. Store a list of messages
  2. Determine whether a message is sent or received
  3. Inflate the appropriate layout within RecyclerView.

But before venturing any further, we need a list of messages!

Engineering a backend for real-time messaging is, however, beyond the scope of this tutorial. We’ll therefore proceed with the models in Sendbird’s chat SDK. It roughly assumes the following structure:

Generic Message and User models

class Message {
    String message;
    User sender;
    long createdAt;

class User {
    String nickname;
    String profileUrl;

Since it is common to design messaging implementations in this manner, you will hopefully be able to follow this tutorial with minimal changes to your code.

Now, let’s create an adapter and name it MessageListAdapter. It will hold a List of Messages that will be displayed within a RecyclerView.

By default, an adapter requires at least one RecyclerView.ViewHolder. It is a layout that can be inflated and bound by the objects it holds. In our case, two ViewHolders are needed:

  1. SentMessageHolder to hold messages that “I” sent
  2. ReceivedMessageHolder to hold messages that “I” have received from others

We’ll write these to be private inner classes of MessageListAdapter.

Each ViewHolder holds member views that can be bound to particular information contained in a message. For example, TextView messageText binds to a message’s content, while nameText binds to the name of a message’s sender.

Antonio Leiva suggests that we implement a bind(object) method within the ViewHolder class. This gives view binding to the ViewHolder class rather than to onBindViewHolder. It therefore produces cleaner code amidst multiple ViewHolders and ViewTypes. It also allows us to add easily OnClickListeners, if necessary.

SentMessageHolder will be identical except that it will not have nameText and profileImage.

Once you complete ViewHolder, turn back to the adapter and override the necessary methods to

  1. Obtain a message from MessageList
  2. Determine whether it is a sent message or a received message
  3. Inflate the appropriate layout for the ViewHolder
  4. Pass the message to the ViewHolder for binding

Implementing this process is standard for most types of adapters, and pretty self-explanatory; therefore, we’ll show the code for the full adapter without further explanation.

We’ve just completed the adapter. We can now display a list of messages, both sent and received, in the chat bubbles that we defined earlier.

Putting it all together

We’ve created all the components, and now we need to initialize them inside our Activity. Instantiate a RecyclerView and a MessageListAdapter with a list of messages, and voila! You’ve just created your own messaging UI.

You can build more advanced features like “image preview,” animated GIFs within chat bubbles, and others. See examples of advanced chat UI at Sendbird’s open source sample UI app! They build upon the use of RecyclerViews and adapters that we covered in this tutorial, and will help you create a production-level chat app with diverse features.

Tags: Engineering