Skip to main content
Version: v5

Building a Conversation List + Message View

The Conversation List + Message View layout offers a seamless two-panel chat interface, commonly used in modern messaging applications like WhatsApp Web, Slack, and Microsoft Teams.

This design enables users to switch between conversations effortlessly while keeping the chat window open, ensuring a smooth, real-time messaging experience.


User Interface Preview

Image

Key Components

  1. Chat Header – Displays user/group name, profile image, and status.
  2. Message List – Shows chat history and new messages.
  3. Message Composer – Allows users to send messages, media, and reactions.

Step-by-Step Guide

Step 1: Setup the Conversations Layout

Define the layout using the CometChatConversations component:

activity_conversations.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConversationActivity">

<com.cometchat.chatuikit.conversations.CometChatConversations
android:id="@+id/conversation_view"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Step 2: Set Up the Conversation Activity

Initialize and handle conversation clicks:

ConversationActivity.kt
import android.content.Intent
import android.os.Bundle

import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity

import com.cometchat.chat.constants.CometChatConstants
import com.cometchat.chat.models.Conversation
import com.cometchat.chat.models.Group
import com.cometchat.chat.models.User
import com.cometchat.chatuikit.conversations.CometChatConversations

class ConversationActivity : AppCompatActivity() {

private lateinit var conversationsView: CometChatConversations

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_conversation)

initView()
setListeners()
}

private fun initView() {
conversationsView = findViewById(R.id.conversation_view)
}

private fun setListeners() {
conversationsView.setOnItemClick { _, _, conversation ->
startMessageActivity(conversation)
}
}

private fun startMessageActivity(conversation: Conversation) {
val intent = Intent(this, MessageActivity::class.java).apply {
when (conversation.conversationType) {
CometChatConstants.CONVERSATION_TYPE_GROUP -> {
val group = conversation.conversationWith as Group
putExtra("guid", group.guid)
}
else -> {
val user = conversation.conversationWith as User
putExtra("uid", user.uid)
}
}
}
startActivity(intent)
}
}
warning

You must use an activity that supports the lifecycle API, such as:

  • AppCompatActivity
  • ComponentActivity
  • FragmentActivity

This is necessary to properly manage the UI Kit's lifecycle events.


Step 3: Setup the Messages Layout

activity_message.xml
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MessageActivity">

<!-- Message Header -->
<com.cometchat.chatuikit.messageheader.CometChatMessageHeader
android:id="@+id/message_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

<!-- Message List -->
<com.cometchat.chatuikit.messagelist.CometChatMessageList
android:id="@+id/message_list"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/message_header"
app:layout_constraintBottom_toTopOf="@id/message_composer"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

<!-- Message Composer -->
<com.cometchat.chatuikit.messagecomposer.CometChatMessageComposer
android:id="@+id/message_composer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Step 4: Configure MessageActivity

Use the user/group passed from the conversation click:

MessageActivity.kt
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import com.cometchat.chat.core.CometChat
import com.cometchat.chat.exceptions.CometChatException
import com.cometchat.chat.models.Group
import com.cometchat.chat.models.User
import com.cometchat.chatuikit.messagecomposer.CometChatMessageComposer
import com.cometchat.chatuikit.messageheader.CometChatMessageHeader
import com.cometchat.chatuikit.messagelist.CometChatMessageList

class MessageActivity : AppCompatActivity() {
private lateinit var messageHeader: CometChatMessageHeader
private lateinit var messageList: CometChatMessageList
private lateinit var messageComposer: CometChatMessageComposer

private var uid: String? = null
private var guid: String? = null

private val TAG = "MessageActivity"

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_message)

initializeViews()
setupChat()
setupHeaderBackButton()
}

private fun initializeViews() {
messageHeader = findViewById(R.id.message_header)
messageList = findViewById(R.id.message_list)
messageComposer = findViewById(R.id.message_composer)
}

private fun setupChat() {
uid = intent.getStringExtra("uid")
guid = intent.getStringExtra("guid")

when {
uid != null -> setupUserChat(uid!!)
guid != null -> setupGroupChat(guid!!)
else -> {
Log.e(TAG, "No user ID or group ID provided")
showError("Missing user ID or group ID")
finish()
}
}
}

private fun setupUserChat(userId: String) {
CometChat.getUser(userId, object : CometChat.CallbackListener<User>() {
override fun onSuccess(user: User) {
Log.d(TAG, "Successfully loaded user: ${user.uid}")
messageHeader.setUser(user)
messageList.setUser(user)
messageComposer.setUser(user)
}

override fun onError(e: CometChatException?) {
Log.e(TAG, "Error loading user: ${e?.message}")
showError("Could not find user: ${e?.message}")
finish()
}
})
}

private fun setupGroupChat(groupId: String) {
CometChat.getGroup(groupId, object : CometChat.CallbackListener<Group>() {
override fun onSuccess(group: Group) {
Log.d(TAG, "Successfully loaded group: ${group.guid}")
messageHeader.setGroup(group)
messageList.setGroup(group)
messageComposer.setGroup(group)
}

override fun onError(e: CometChatException?) {
Log.e(TAG, "Error loading group: ${e?.message}")
showError("Could not find group: ${e?.message}")
finish()
}
})
}

private fun setupHeaderBackButton() {
messageHeader.setOnBackButtonPressed {
finish()
}
}

private fun showError(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}

Step 5: Update MainActivity

Update the MainActivity to navigate to the MessageActivity:

MainActivity.kt
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.enableEdgeToEdge
import com.cometchat.chat.core.CometChat
import com.cometchat.chat.exceptions.CometChatException
import com.cometchat.chat.models.User
import com.cometchat.chatuikit.shared.cometchatuikit.CometChatUIKit
import com.cometchat.chatuikit.shared.cometchatuikit.UIKitSettings

class MainActivity : ComponentActivity() {

private val TAG = "MainActivity"

private val appID = "APP_ID" // Replace with your App ID
private val region = "REGION" // Replace with your App Region
private val authKey = "AUTH_KEY" // Replace with your Auth Key or leave blank if you are authenticating using Auth Token

private val uiKitSettings = UIKitSettings.UIKitSettingsBuilder()
.setRegion(region)
.setAppId(appID)
.setAuthKey(authKey)
.subscribePresenceForAllUsers()
.build()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()

CometChatUIKit.init(this, uiKitSettings, object : CometChat.CallbackListener<String?>() {
override fun onSuccess(successString: String?) {

Log.d(TAG, "Initialization completed successfully")

loginUser()
}

override fun onError(e: CometChatException?) {}
})
}

private fun loginUser() {
CometChatUIKit.login("cometchat-uid-1", object : CometChat.CallbackListener<User>() {
override fun onSuccess(user: User) {

// Launch Conversation List + Message View (Split-Screen Style)
startActivity(Intent(this@MainActivity, ConversationActivity::class.java))
}

override fun onError(e: CometChatException) {
// Handle login failure (e.g. show error message or retry)
Log.e("Login", "Login failed: ${e.message}")
}
})
}
}

Running the Project

Once the components are configured, build and run the app:

gradle build

Ensure you've added the necessary permissions and initialized CometChat in your Application class.


Next Steps

Enhance the User Experience