Skip to main content

Message Input#

MessageInputView is the view used to create a new chat message and send it to a channel.

First custom MessageInputView exampleFirst custom MessageInputView example

It supports the following features:

  • Emoticons
  • Attachments
  • Slash Commands
  • Typing events
  • Editing messages
  • Threads
  • Mentions
  • Replies


To use MessageInputView, include it in your XML layout. It usually goes below a MessageListView.

<        android:id="@+id/messageInputView"        android:layout_width="0dp"        android:layout_height="wrap_content"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toBottomOf="@+id/messageListView"        />

The recommended way of setting up the input view is by binding it to a MessageInputViewModel. This will make it fully functional by setting up any necessary listeners and data handling.

// Instantiate the ViewModel for a given channelval factory: MessageListViewModelFactory = MessageListViewModelFactory(cid = "channelType:channelId")val viewModel: MessageInputViewModel by viewModels { factory }// Bind it with MessageInputViewviewModel.bindView(messageInputView, viewLifecycleOwner)

Handling Actions#

Actions can be handled by setting listeners on this view. For example, you can handle clicks of the send button or when the user starts and stops typing:

messageInputView.setOnSendButtonClickListener {    // Handle send button click}
messageInputView.setTypingListener(    object : MessageInputView.TypingListener {        override fun onKeystroke() {            // Handle keystroke case        }
        override fun onStopTyping() {            // Handle stop typing case        }    })

You can show a custom error when the maximum message length is exceeded:

messageInputView.setMaxMessageLengthHandler { messageText, messageLength, maxMessageLength, maxMessageLengthExceeded ->    if (maxMessageLengthExceeded)  {        // Show custom max-length error    } else {        // Hide custom max-length error    }}

You can also change the handler that sends messages. By default, this is set up by bindView and calls into the ViewModel to perform these actions.

messageInputView.setSendMessageHandler(    object : MessageInputView.MessageSendHandler {        override fun sendMessage(messageText: String, messageReplyTo: Message?) {            // Handle send message        }
        override fun sendMessageWithAttachments(            message: String,            attachmentsWithMimeTypes: List<Pair<File, String?>>,            messageReplyTo: Message?,        ) {            // Handle message with attachments        }
        override fun sendToThreadWithAttachments(            parentMessage: Message,            message: String,            alsoSendToChannel: Boolean,            attachmentsWithMimeTypes: List<Pair<File, String?>>,        ) {           // Handle message to thread with attachments        }
        override fun sendToThread(parentMessage: Message, messageText: String, alsoSendToChannel: Boolean) {            // Handle message to thread        }
        override fun editMessage(oldMessage: Message, newMessageText: String) {            // Handle edit message        }
        override fun dismissReply() {            // Handle dismiss reply        }    })


MessageInputView can be customized in two ways: using XML attributes and programmatically using style transformations.

Using XML Attributes#

Many attributes of this View can be configured, like changing its color, the border and the color of the message input, fonts, components visibility, and so on. The full list of available attributes can be found here.

Here's an example of setting some custom attributes:

<    android:id="@+id/messageInputView"    android:layout_width="0dp"    android:layout_height="wrap_content"    android:background="@color/grey_light"    app:streamUiMessageInputEditTextBackgroundDrawable="@drawable/stream_ui_shape_edit_text_squared"    app:streamUiMessageInputTextStyle="italic"    app:streamUiMessageInputDividerBackgroundDrawable="@drawable/stream_ui_divider_green"    app:streamUiMessageInputTextColor="@color/stream_ui_white"    />

This will create this version of MessageInputView:

First custom MessageInputView example

Here's another example with different attributes set:

<    android:id="@+id/messageInputView"    android:layout_width="0dp"    android:layout_height="wrap_content"    app:layout_constraintBottom_toBottomOf="parent"    app:layout_constraintEnd_toEndOf="parent"    app:layout_constraintStart_toStartOf="parent"    app:layout_constraintTop_toBottomOf="@+id/messageListView"    app:streamUiMessageInputEditTextBackgroundDrawable="@drawable/stream_ui_shape_edit_text_rounded"    app:streamUiMessageInputTextStyle="italic"    android:background="@color/stream_ui_black"    app:streamUiMessageInputDividerBackgroundDrawable="@drawable/stream_ui_divider_green"    app:streamUiMessageInputTextColor="@color/stream_ui_white"    />

This produces the following styling:

Second custom MessageInputView example

Different configurations can be used to achieve the desired appearance of MessageListView. If you don't need to change this View appearance at runtime, XML should be enough. But if you need to able to customize it at runtime, then you can use MessageInputViewStyle as described in the next section.

Using Style Transformations#

You can use TransformStyle to apply global style transformations to all MessageInputView instances. For example, you can create set up a messageInputStyleTransformer like this one to change the input text color:

TransformStyle.messageInputStyleTransformer = StyleTransformer { viewStyle ->    viewStyle.copy(        messageInputTextColor = ContextCompat.getColor(requireContext(), R.color.stream_ui_white)    )}

The transformer should be set before the View is rendered to make sure that the new style was applied.

Creating Custom Suggestion Items#

The suggestion list popup is used to provide autocomplete suggestions for commands and mentions. To customize the appearance of suggestion list items you need to provide your own SuggestionListViewHolderFactory. Here's an example of a custom command item that displays just a command name:

  1. Create the item_command.xml layout:
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android=""    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:background="?attr/selectableItemBackground"    android:paddingStart="16dp"    android:paddingEnd="16dp"    android:paddingTop="8dp"    android:paddingBottom="8dp">
    <TextView        android:id="@+id/commandNameTextView"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />
  1. Create a custom ViewHolder that extends BaseSuggestionItemViewHolder, and a custom ViewHolder factory which extends SuggestionListItemViewHolderFactory:
class CustomSuggestionListViewHolderFactory : SuggestionListItemViewHolderFactory() {    override fun createCommandViewHolder(        parent: ViewGroup,    ): BaseSuggestionItemViewHolder<SuggestionListItem.CommandItem> {        return ItemCommandBinding            .inflate(LayoutInflater.from(parent.context), parent, false)            .let(::CustomCommandViewHolder)    }}
class CustomCommandViewHolder(    private val binding: ItemCommandBinding,) : BaseSuggestionItemViewHolder<SuggestionListItem.CommandItem>(binding.root) {
    override fun bindItem(item: SuggestionListItem.CommandItem) {        binding.commandNameTextView.text =    }}
  1. Set the custom ViewHolder factory on MessageInputView:

This produces the following result:

Custom suggestion item

Changing Mention Search#

It is possible to change the search method in the mention list. The default class: DefaultUserLookupHandler removes diacritics and uses levenstein distance to include similar words in the results.

val defaultUserLookupHandler = DefaultUserLookupHandler(users)messageInputView.setUserLookupHandler(defaultUserLookupHandler)


You can add transliteration to DefaultUserLookupHandler by setting the desired id for transliteration inside DefaultStreamTransliterator and passing it to DefaultUserLookupHandler constructor.


DefaultStreamTransliterator only supports transliteration prior to API 29 (Android Q) and it will not apply transliteration for APIs smaller than this.

val defaultUserLookupHandler = DefaultUserLookupHandler(    users,    DefaultStreamTransliterator("Cyrl-Latn"))messageInputView.setUserLookupHandler(defaultUserLookupHandler)

You can also use your own implementation of StreamTransliterator to add support for lowers APIs. An interesting library is ICU4J

Attachment Size Limits#

There is a limit for the size of attachments in this View. The default value is 20MB, and selecting a file larger than that limit will notify the user:

Big file feedback

You can use MessageInputViewStyle.attachmentMaxFileSize to change the maximum allowed size of attachments. However, there's a 20MB limit in Stream Chat's CDN as well. To send larger attachments, you can use your own CDN.

You can listen for large attachments being added to the list of attachments (for example, to present a custom message to the user in this case) with MessageInputView.listenForBigAttachments.

Did you find this page helpful?