Skip to main content
This guide walks you through creating a tab-based messaging UI using React and CometChat UIKit. The UI will include different sections for Chats, Calls, Users, and Groups, allowing seamless navigation.

User Interface Preview

This layout consists of:
  1. Sidebar (Conversation List) – Displays recent conversations with active users and groups.
  2. Message View – Shows the selected chat with real-time messages.
  3. Message Input Box – Allows users to send messages seamlessly.

Step-by-Step Guide

Step 1: Create a Tab Component

To manage navigation, let’s build a CometChatTabs component. This component will render different tabs and allow switching between sections dynamically.

Folder Structure

Create a TabbedActivity inside your src directory and add the following files:
src/main/java/your-package-name/
├── TabbedActivity.kt
├── ChatsFragment.kt
├── CallLogsFragment.kt
├── UsersFragment.kt
├── GroupsFragment.kt

src/main/java/your-package-name/
├── res/
│   ├── layout/
│   │   ├── activity_tabbed.xml
│   │   ├── fragment_chats.xml
│   │   ├── fragment_call_logs.xml
│   │   ├── fragment_users.xml
│   │   └── fragment_groups.xml
│   └── menu/
│       └── bottom_nav_menu.xml

Download the Icons

These icons are available in the CometChat UI Kit res folder. You can find them at:
🔗 GitHub Assets Folder

Implementation

  • Kotlin
  • Java
  • XML
TabbedActivity.kt
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment

import com.google.android.material.bottomnavigation.BottomNavigationView

class TabbedActivity : AppCompatActivity() {

    private lateinit var bottomNavigationView: BottomNavigationView

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

        setupWindowInsets()
        initViews()
        setupNavigation(savedInstanceState)
    }

    private fun setupWindowInsets() {
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }
    }

    private fun initViews() {
        bottomNavigationView = findViewById(R.id.bottomNavigationView)
    }

    private fun setupNavigation(savedInstanceState: Bundle?) {
        bottomNavigationView.setOnItemSelectedListener { item ->
            val fragment = createFragmentForNavItem(item.itemId)
            replaceFragment(fragment)
            true
        }

        // Set default fragment only when activity is first created
        if (savedInstanceState == null) {
            replaceFragment(ChatsFragment())
            bottomNavigationView.selectedItemId = R.id.nav_chats
        }
    }

    private fun createFragmentForNavItem(itemId: Int): Fragment {
        return when (itemId) {
            R.id.nav_chats -> ChatsFragment()
            R.id.nav_call_logs -> CallLogsFragment()
            R.id.nav_users -> UsersFragment()
            R.id.nav_groups -> GroupsFragment()
            else -> ChatsFragment()
        }
    }

    private fun replaceFragment(fragment: Fragment) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.fragmentContainer, fragment)
            .commit()
    }
}
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: Create Fragments for Chat, Calls, Users and Groups

Chats Fragment

  • Kotlin
  • Java
  • XML
ChatsFragment.kt
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

import androidx.fragment.app.Fragment

class ChatsFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_chats, container, false)
    }
}

Call Logs Fragment

Make sure you’ve added the Calls SDK dependency to enable voice and video calling features.
  • Kotlin
  • Java
  • XML
CallLogsFragment.kt
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

import androidx.fragment.app.Fragment

class CallLogsFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_call_logs, container, false)
    }
}

Users Fragment

  • Kotlin
  • Java
  • XML
UsersFragment.kt
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

import androidx.fragment.app.Fragment

class UsersFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_users, container, false)
    }
}

Groups Fragment

  • Kotlin
  • Java
  • XML
GroupsFragment.kt
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

import androidx.fragment.app.Fragment

class GroupsFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_groups, container, false)
    }
}

Step 3: Update MainActivity

Update the MainActivity to navigate to the MessageActivity:
  • Kotlin
  • Java
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 Tab-Based Chat Experience (Chats, Calls, Users, Groups)
                startActivity(Intent(this@MainActivity, TabbedActivity::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


I