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.

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.

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.

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.

StreamMessageListView(
    ...
    messageBuilder: (context, messageDetails, messageList, defaultWidget) {
        return defaultWidget;
    },
)

We use .copyWith() to customize the widget:

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.

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

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:

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)}](/chat/docs/sdk/flutter/stream_chat_flutter/custom_widgets/customize_text_messages/${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.

© Getstream.io, Inc. All Rights Reserved.