Skip to main content
CometChatMessageComposer renders the message input area and sends messages to the active conversation. It supports text, media, mentions, voice notes, stickers, and AI-powered features.

Where It Fits

CometChatMessageComposer is an input component. Wire it with CometChatMessageHeader and CometChatMessageList to build a complete messaging layout.
activity_chat.xml
<com.cometchat.uikit.kotlin.presentation.messagecomposer.ui.CometChatMessageComposer
    android:id="@+id/message_composer"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
val messageComposer = findViewById<CometChatMessageComposer>(R.id.message_composer)
messageComposer.setUser(user)

Quick Start

Add to your layout XML:
<com.cometchat.uikit.kotlin.presentation.messagecomposer.ui.CometChatMessageComposer
    android:id="@+id/composer"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
Set a User or Group:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.your_layout)

    val composer = findViewById<CometChatMessageComposer>(R.id.composer)
    composer.setUser(user)
    // or composer.setGroup(group)
}
Prerequisites: CometChat SDK initialized with CometChatUIKit.init(), a user logged in, and the UI Kit dependency added.
The MessageComposer manages runtime permissions. To ensure the ActivityResultLauncher is properly initialized, create the composer in the onCreate state of an activity. If using a fragment, load it in the activity’s onCreate.

Actions and Events

Callback Methods

onSendButtonClick

Fires when the send button is tapped. Override to intercept or replace the default message-sending logic.
messageComposer.setOnSendButtonClick { context, baseMessage ->
    // Custom send logic
}

onError

Fires on internal errors (network failure, auth issue, SDK exception).
messageComposer.setOnError { context, exception ->
    Log.e("Composer", "Error: ${exception.message}")
}

SDK Events

The MessageComposer does not attach SDK listeners directly. Typing indicators are managed internally when disableTypingEvents is false (default).

Functionality

Method (Kotlin XML)Compose ParameterDescription
setUser(user)user = userSet target user for 1-on-1 conversations
setGroup(group)group = groupSet target group for group conversations
setOnSendButtonClick { }onSendButtonClick = { }Override send button behavior
setParentMessageId(id)parentMessageId = idSet parent message ID for threaded replies
setTextFormatters(list)textFormatters = listCustom text formatters (mentions, etc.)
setEnableRichTextFormatting(true)enableRichTextFormatting = trueEnable rich text formatting

Custom View Slots

Header View

Custom view above the text input area.
val view = LayoutInflater.from(context).inflate(R.layout.custom_header_layout, null)
messageComposer.setHeaderView(view)

Send Button View

Replace the default send button.
val imageView = ImageView(this)
imageView.setImageResource(R.drawable.custom_send_button)
imageView.setOnClickListener {
    Toast.makeText(this, "Custom Send Button Clicked!", Toast.LENGTH_SHORT).show()
}
messageComposer.setSendButtonView(imageView)

Auxiliary Button View

Replace the auxiliary button area (stickers, AI).
If you override the auxiliary button with setAuxiliaryButtonView(), retrieve the default auxiliary buttons via CometChatUIKit.getDataSource().getAuxiliaryOption() and include them in your custom layout to preserve sticker/AI buttons.
val linearLayout = LinearLayout(this)
linearLayout.orientation = LinearLayout.HORIZONTAL

// Preserve default auxiliary buttons
val defaultView = CometChatUIKit.getDataSource().getAuxiliaryOption(
    this, user, group,
    messageComposer.composerViewModel.getIdMap(),
    messageComposer.additionParameter
)
linearLayout.addView(defaultView)

// Add custom button
val customButton = ImageView(this)
customButton.setImageResource(R.drawable.save_icon)
linearLayout.addView(customButton)

messageComposer.setAuxiliaryButtonView(linearLayout)

Attachment Options

Replace the default attachment options.
val actionList = ArrayList<CometChatMessageComposerAction>()

val action1 = CometChatMessageComposerAction()
action1.title = "Custom Option 1"
action1.icon = R.drawable.ic_cp_1
action1.onClick = {
    Toast.makeText(context, "Custom Option 1", Toast.LENGTH_SHORT).show()
}
actionList.add(action1)

messageComposer.setAttachmentOptions(actionList)

Text Formatters (Mentions)

val mentionFormatter = CometChatMentionsFormatter(context)
mentionFormatter.setMessageComposerMentionTextStyle(context, R.style.CustomMentionsStyle)

val textFormatters: MutableList<CometChatTextFormatter> = ArrayList()
textFormatters.add(mentionFormatter)
messageComposer.setTextFormatters(textFormatters)

Style

Define a custom style in themes.xml:
themes.xml
<style name="CustomMessageComposerStyle" parent="CometChatMessageComposerStyle">
    <item name="cometchatMessageComposerBackgroundColor">#FEEDE1</item>
    <item name="cometchatMessageComposerInputBackgroundColor">#FFFFFF</item>
</style>

<style name="AppTheme" parent="CometChatTheme.DayNight">
    <item name="cometchatMessageComposerStyle">@style/CustomMessageComposerStyle</item>
</style>
See Component Styling for the full reference.

ViewModel

val viewModel = ViewModelProvider(this)
    .get(CometChatMessageComposerViewModel::class.java)
messageComposer.setViewModel(viewModel)
See ViewModel & Data for state observation and custom repositories.

Next Steps

Message List

Display messages in a conversation

Message Header

Display user/group info in the toolbar

Message Template

Customize message bubble structure

Component Styling

Detailed styling reference