--- id: customize_text_messages title: 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. :::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. ::: ### 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. :::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. ::: ```dart StreamMessageListView( ... messageBuilder: (context, messageDetails, messageList, defaultWidget) { return defaultWidget; }, ) ``` We use `.copyWith()` to customize the widget: ```dart StreamMessageListView( ... messageBuilder: (context, messageDetails, messageList, defaultWidget) { return defaultWidget.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, messageDetails, messageList, defaultWidget) { return defaultWidget.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.parameter ```dart StreamMessageListView( ... messageBuilder: (context, messageDetails, messageList, defaultWidget) { return defaultWidget.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, messageDetails, messageList, defaultWidget) { return defaultWidget.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){ text = text!.replaceAll( '${match.group(0)}', '[${match.group(0)}](${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. ![](../../assets/hashtag_example.jpg)