Skip to main content

Custom Message Bubble Builders

Use customMessageBubbleBuilders to provide custom content for selected MessageType values.

This is a callback entry point. The builder returns a Widget for the message content area. The built-in message row still owns avatar placement, alignment, status indicators, read-receipt display, and long-press behavior.

Callback Signature

Dart
typedef ChatMessageBubbleBuilder = Widget Function(
BuildContext context,
Message message,
ChatPageConfig config,
);

You can register builders in either place:

  • ChatPage.customMessageBubbleBuilders
  • ChatPageConfig.customMessageBubbleBuilders

The constructor argument on ChatPage takes precedence when both are provided.

Register a Builder

Dart
ChatPage(
channel: channel,
customMessageBubbleBuilders: {
MessageType.custom: (context, message, config) {
return const Text('Custom payload');
},
},
)

Render a Custom Message Payload

Dart
Widget customPayloadBubble(
BuildContext context,
Message message,
ChatPageConfig config,
) {
final custom = message is CustomMessage ? message : null;
final fields = custom?.fields ?? const {};
final title = fields['title']?.toString() ?? 'Custom message';
final body = fields['body']?.toString() ?? '';

return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: config.bubbleConfig.receivedStyle.textStyle ??
const TextStyle(fontWeight: FontWeight.w600),
),
if (body.isNotEmpty) ...[
const SizedBox(height: 6),
Text(body),
],
],
);
}

ChatPage(
channel: channel,
config: ChatPageConfig(
customMessageBubbleBuilders: {
MessageType.custom: customPayloadBubble,
MessageType.userCustom: customPayloadBubble,
MessageType.customMessage: customPayloadBubble,
},
),
)

Keep the Callback Small

The builder is called during message list rendering, so keep heavy work outside the widget tree. Parse the message payload cheaply, delegate async work to your provider layer, and return a stable widget.

Full Row Replacement

If you need to replace the complete row instead of just the bubble content, use ChatPage.messageBuilder. See Chat page builders.