# Message List View

Customizing Text Messages

### Introduction

Every application provides a unique look and feel to their own messaging interface including and not
limited to fonts, colors, and shapes.

This guide details how to customize message text in the `StreamMessageListView` / `StreamMessageWidget` in the
Stream Chat Flutter UI SDK.

<admonition type="note">

This guide is specifically for the `StreamMessageListView` but if you intend to display a `StreamMessageWidget`
separately, follow the same process without the `.copyWith` and use the default constructor instead.

</admonition>

### Basics of customizing a `StreamMessageWidget`

First, add a `StreamMessageListView` in the appropriate place where you intend to display messages from a
channel.

```dart
StreamMessageListView(
    ...
)
```

Now, we use the `messageBuilder` parameter to build a custom message. The builder function also provides
the default implementation of the `StreamMessageWidget` so that we can change certain aspects of the widget
without redoing all of the default parameters.

<admonition type="note">

In earlier versions of the SDK, some `StreamMessageWidget` parameters were exposed directly through the `StreamMessageListView`,
however, this quickly becomes hard to maintain as more parameters and customizations are added to the
`StreamMessageWidget`. Newer version utilise a cleaner interface to change the parameters by supplying a
default message implementation as aforementioned.

</admonition>

```dart
StreamMessageListView(
    ...
    messageBuilder: (context, message, defaultProps) {
        return StreamMessageWidget.fromProps(props: defaultProps);
    },
)
```

We use `.copyWith()` to customize the widget:

```dart
StreamMessageListView(
    ...
    messageBuilder: (context, message, defaultProps) {
        return StreamMessageWidget.fromProps(
            props: defaultProps.copyWith(
                ...
            ),
        );
    },
)
```

### Customizing text

If you intend to simply change the theme for the text, you need not recreate the whole widget. The
`StreamMessageWidget` has a `messageTheme` parameter that allows you to pass the theme for most aspects
of the message.

```dart
StreamMessageListView(
    ...
    messageBuilder: (context, message, defaultProps) {
        return StreamMessageWidget.fromProps(
            props: defaultProps.copyWith(
                messageTheme: StreamMessageThemeData(
                    ...
                    messageTextStyle: TextStyle(),
                ),
            ),
        );
    },
)
```

If you want to replace the entire text widget in the `StreamMessageWidget`, you can use the `textBuilder`
parameter which provides a builder for creating a widget to substitute the default text.

```dart
StreamMessageListView(
    ...
    messageBuilder: (context, message, defaultProps) {
        return StreamMessageWidget.fromProps(
            props: defaultProps.copyWith(
                textBuilder: (context, message) {
                    return Text(message.text ?? '');
                },
            ),
        );
    },
)
```

### Adding Hashtags

To add elements like hashtags, we can override the `textBuilder` in the StreamMessageWidget:

```dart
StreamMessageListView(
    ...
    messageBuilder: (context, message, defaultProps) {
        return StreamMessageWidget.fromProps(
            props: defaultProps.copyWith(
                textBuilder: (context, message) {
                    final text = _replaceHashtags(message.text)?.replaceAll('\n', '\\\n');
                    final messageTheme = StreamChatTheme.of(context).ownMessageTheme;

                    if (text == null) return const SizedBox();

                    return MarkdownBody(
                        data: text,
                        onTapLink: (
                            String link,
                            String? href,
                            String title,
                            ) {
                          // Do something with tapped hashtag
                        },
                        styleSheet: MarkdownStyleSheet.fromTheme(
                          Theme.of(context).copyWith(
                            textTheme: Theme.of(context).textTheme.apply(
                              bodyColor: messageTheme.messageTextStyle?.color,
                              decoration: messageTheme.messageTextStyle?.decoration,
                              decorationColor: messageTheme.messageTextStyle?.decorationColor,
                              decorationStyle: messageTheme.messageTextStyle?.decorationStyle,
                              fontFamily: messageTheme.messageTextStyle?.fontFamily,
                            ),
                          ),
                        ).copyWith(
                          a: messageTheme.messageLinksStyle,
                          p: messageTheme.messageTextStyle,
                        ),
                    );
                },
            ),
        );
    },
)

String? _replaceHashtags(String? text) {
  if (text == null) return null;

  final exp = RegExp(r'\B#\w\w+');
  String result = text;
  exp.allMatches(text).forEach((match) {
    result = result.replaceAll(
      '${match.group(0)}',
      '[${match.group(0)}](hashtag:${match.group(0)?.replaceAll(' ', '')})',
    );
  });
  return result;
}
```

We can replace the hashtags using RegEx and add links for the MarkdownBody which is done here in the
`_replaceHashtags()` function.
Inside the textBuilder, we use the `flutter_markdown` package to build our hashtags as links.

![](@chat-sdk/flutter/v10-latest/_assets/hashtag_example.jpg)


---

This page was last updated at 2026-04-23T18:43:03.973Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/flutter/v10/stream_chat_flutter/custom_widgets/customize_text_messages/](https://getstream.io/chat/docs/sdk/flutter/v10/stream_chat_flutter/custom_widgets/customize_text_messages/).