> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-rn-guide-message-privately.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Text Formatters

> Create custom text processors for hashtags, mentions, links, or any pattern using the CometChatTextFormatter API.

Text formatters let you process message text with tracking characters, suggestion lists, and spannable transformations. Use them to add hashtag detection, custom mentions, link previews, or any text pattern processing.

## CometChatTextFormatter

The `CometChatTextFormatter` abstract class is the base for all formatters. Its constructor takes a `char trackingCharacter` that triggers the formatter when typed in the composer (e.g., `@` for mentions, `#` for hashtags).

### Key Override Methods

| Method                                                                        | Purpose                                                                                             |
| ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `search(Context, String)`                                                     | Called when the user types after the tracking character. Use this to fetch and display suggestions. |
| `onScrollToBottom()`                                                          | Called when the user scrolls to the bottom of the suggestion list. Use for pagination.              |
| `prepareLeftMessageBubbleSpan(Context, BaseMessage, SpannableStringBuilder)`  | Apply spans to text in received (left) message bubbles.                                             |
| `prepareRightMessageBubbleSpan(Context, BaseMessage, SpannableStringBuilder)` | Apply spans to text in sent (right) message bubbles.                                                |
| `prepareComposerSpan(Context, BaseMessage, SpannableStringBuilder)`           | Apply spans to text in the message composer.                                                        |
| `prepareConversationSpan(Context, BaseMessage, SpannableStringBuilder)`       | Apply spans to the last message preview in the conversations list.                                  |

### Pre-Send Hook

Override `handlePreMessageSend(Context, BaseMessage)` to modify a message before it's sent. This is useful for attaching metadata, transforming text, or adding custom data to the message object.

## Suggestion System

The formatter provides a built-in suggestion dropdown:

| Method                                              | Description                                            |
| --------------------------------------------------- | ------------------------------------------------------ |
| `setSuggestionItemList(List<SuggestionItem>)`       | Set the list of suggestions to display                 |
| `setShowLoadingIndicator(boolean)`                  | Show/hide a loading spinner in the suggestion dropdown |
| `setDisableSuggestions(boolean)`                    | Disable the suggestion dropdown entirely               |
| `onItemClick(Context, SuggestionItem, User, Group)` | Called when the user selects a suggestion item         |

## Example: Custom Hashtag Formatter

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    class HashtagFormatter : CometChatTextFormatter('#') {

        override fun search(context: Context, queryString: String?) {
            // Fetch hashtag suggestions based on query
            val suggestions = fetchHashtags(queryString)
            setSuggestionItemList(suggestions)
        }

        override fun onScrollToBottom() {
            // Load more suggestions
        }

        override fun prepareLeftMessageBubbleSpan(
            context: Context,
            baseMessage: BaseMessage,
            spannable: SpannableStringBuilder
        ): SpannableStringBuilder? {
            // Apply blue color to #hashtags in received messages
            applyHashtagSpans(spannable, context)
            return spannable
        }

        override fun prepareRightMessageBubbleSpan(
            context: Context,
            baseMessage: BaseMessage,
            spannable: SpannableStringBuilder
        ): SpannableStringBuilder? {
            // Apply blue color to #hashtags in sent messages
            applyHashtagSpans(spannable, context)
            return spannable
        }

        override fun prepareComposerSpan(
            context: Context,
            baseMessage: BaseMessage,
            spannable: SpannableStringBuilder
        ): SpannableStringBuilder? {
            applyHashtagSpans(spannable, context)
            return spannable
        }

        override fun prepareConversationSpan(
            context: Context,
            baseMessage: BaseMessage,
            spannable: SpannableStringBuilder
        ): SpannableStringBuilder? {
            applyHashtagSpans(spannable, context)
            return spannable
        }
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    public class HashtagFormatter extends CometChatTextFormatter {

        public HashtagFormatter() {
            super('#');
        }

        @Override
        public void search(@Nonnull Context context, @Nullable String queryString) {
            // Fetch hashtag suggestions based on query
            List<SuggestionItem> suggestions = fetchHashtags(queryString);
            setSuggestionItemList(suggestions);
        }

        @Override
        public void onScrollToBottom() {
            // Load more suggestions
        }

        @Nullable
        @Override
        public SpannableStringBuilder prepareLeftMessageBubbleSpan(
                @Nonnull Context context,
                @Nonnull BaseMessage baseMessage,
                SpannableStringBuilder spannable) {
            applyHashtagSpans(spannable, context);
            return spannable;
        }

        @Nullable
        @Override
        public SpannableStringBuilder prepareRightMessageBubbleSpan(
                @Nonnull Context context,
                @Nonnull BaseMessage baseMessage,
                SpannableStringBuilder spannable) {
            applyHashtagSpans(spannable, context);
            return spannable;
        }

        @Nullable
        @Override
        public SpannableStringBuilder prepareComposerSpan(
                @Nonnull Context context,
                @Nonnull BaseMessage baseMessage,
                SpannableStringBuilder spannable) {
            applyHashtagSpans(spannable, context);
            return spannable;
        }

        @Nullable
        @Override
        public SpannableStringBuilder prepareConversationSpan(
                @Nonnull Context context,
                @Nonnull BaseMessage baseMessage,
                SpannableStringBuilder spannable) {
            applyHashtagSpans(spannable, context);
            return spannable;
        }
    }
    ```
  </Tab>
</Tabs>

## Registering Formatters

Register formatters on a component using `setTextFormatters`:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    val hashtagFormatter = HashtagFormatter()
    conversations.setTextFormatters(listOf(hashtagFormatter))
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    HashtagFormatter hashtagFormatter = new HashtagFormatter();
    conversations.setTextFormatters(Arrays.asList(hashtagFormatter));
    ```
  </Tab>
</Tabs>

## Built-in Formatter: CometChatMentionsFormatter

The UI Kit includes `CometChatMentionsFormatter` as a built-in formatter that handles `@mention` detection, user suggestion lists, and spannable highlighting. It serves as a reference implementation for building custom formatters.

See the [Mentions Formatter Guide](/ui-kit/android/mentions-formatter-guide) for details.

## Global Configuration via DataSource

Formatters can also be configured globally using the `DataSource` framework. Override `getTextFormatters` in a `DataSourceDecorator` to add formatters that apply across all components:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    class CustomDataSource(dataSource: DataSource) : DataSourceDecorator(dataSource) {
        override fun getTextFormatters(context: Context, additionParameter: AdditionParameter): List<CometChatTextFormatter> {
            val formatters = super.getTextFormatters(context, additionParameter).toMutableList()
            formatters.add(HashtagFormatter())
            return formatters
        }
    }

    // Register globally
    ChatConfigurator.enable { dataSource -> CustomDataSource(dataSource) }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    public class CustomDataSource extends DataSourceDecorator {
        public CustomDataSource(DataSource dataSource) {
            super(dataSource);
        }

        @Override
        public List<CometChatTextFormatter> getTextFormatters(Context context, AdditionParameter additionParameter) {
            List<CometChatTextFormatter> formatters = new ArrayList<>(super.getTextFormatters(context, additionParameter));
            formatters.add(new HashtagFormatter());
            return formatters;
        }
    }

    // Register globally
    ChatConfigurator.enable(dataSource -> new CustomDataSource(dataSource));
    ```
  </Tab>
</Tabs>

## Related

* [DataSource & ChatConfigurator](/ui-kit/android/customization-datasource) — Learn the full DataSource decorator framework.
* [Mentions Formatter Guide](/ui-kit/android/mentions-formatter-guide) — Built-in mentions formatter reference.
* [Customization Overview](/ui-kit/android/customization-overview) — See all customization categories.
