Skip to main content
FieldValue
Packagecometchat_chat_uikit
Key classCometChatUrlFormatter (extends CometChatTextFormatter)
Required setupCometChatUIKit.init(uiKitSettings: uiKitSettings) then CometChatUIKit.login("UID")
PurposeAuto-detects URLs in text messages and converts them to clickable links
Sample appGitHub
RelatedCustom Text Formatter | All Guides
CometChatUrlFormatter extends CometChatTextFormatter to detect URLs in text messages and render them as clickable links.

Overview

The URL formatter is included by default in the Flutter UI Kit. It automatically:
  • Detects URLs in message text using regex patterns
  • Styles URLs with underline and link color
  • Opens URLs in the browser when tapped

Default Behavior

The CometChatUrlFormatter is automatically applied to messages. URLs are:
  • Styled with underline decoration
  • Colored based on bubble alignment (white for outgoing, info color for incoming)
  • Clickable - tapping opens the URL in the default browser

Usage

Basic Usage (Default)

The URL formatter is included by default. No additional setup required.
CometChatMessageList(
  user: chatUser,
  // URL formatter is automatically included
)

Custom URL Formatter

Create a custom URL formatter with your own styling and behavior.
import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

class CustomUrlFormatter extends CometChatUrlFormatter {
  CustomUrlFormatter() : super(
    pattern: RegExp(r'(https?:\/\/[^\s]+)'),
    messageBubbleTextStyle: (context, alignment, {forConversation}) {
      return TextStyle(
        color: Colors.blue,
        decoration: TextDecoration.underline,
        decorationColor: Colors.blue,
      );
    },
  );

  @override
  List<AttributedText> getAttributedText(
    String text, 
    BuildContext context, 
    BubbleAlignment? alignment,
    {List<AttributedText>? existingAttributes,
    Function(String)? onTap,
    bool forConversation = false}
  ) {
    return super.getAttributedText(
      text, context, alignment,
      existingAttributes: existingAttributes,
      onTap: onTap ?? (url) async {
        // Custom URL handling
        _trackUrlClick(url);
        await _openUrl(url);
      },
      forConversation: forConversation,
    );
  }

  void _trackUrlClick(String url) {
    // Add analytics tracking
    print('URL clicked: $url');
  }

  Future<void> _openUrl(String url) async {
    if (!url.startsWith('http://') && !url.startsWith('https://')) {
      url = 'https://$url';
    }
    final uri = Uri.parse(url);
    if (await canLaunchUrl(uri)) {
      await launchUrl(uri, mode: LaunchMode.externalApplication);
    }
  }
}

Apply Custom Formatter

CometChatMessageList(
  user: chatUser,
  textFormatters: [
    CustomUrlFormatter(),
    CometChatMentionsFormatter(), // Keep other formatters
  ],
)

Customization

Override getMessageBubbleTextStyle to customize link appearance:
@override
TextStyle getMessageBubbleTextStyle(
  BuildContext context, 
  BubbleAlignment? alignment,
  {bool forConversation = false}
) {
  CometChatColorPalette colorPalette = CometChatThemeHelper.getColorPalette(context);
  
  return TextStyle(
    color: alignment == BubbleAlignment.right 
      ? colorPalette.white 
      : colorPalette.info,
    fontWeight: FontWeight.w500,
    decoration: TextDecoration.underline,
    decorationColor: alignment == BubbleAlignment.right 
      ? colorPalette.white 
      : colorPalette.info,
  );
}

Custom URL Pattern

Use a custom regex pattern to match specific URL formats:
CometChatUrlFormatter(
  pattern: RegExp(
    r'(https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*))'
  ),
)

Handle URL Clicks

Override getAttributedText to add custom click handling:
@override
List<AttributedText> getAttributedText(
  String text, 
  BuildContext context, 
  BubbleAlignment? alignment,
  {List<AttributedText>? existingAttributes,
  Function(String)? onTap,
  bool forConversation = false}
) {
  return super.getAttributedText(
    text, context, alignment,
    existingAttributes: existingAttributes,
    onTap: (url) async {
      // Show confirmation dialog before opening
      final shouldOpen = await showDialog<bool>(
        context: context,
        builder: (context) => AlertDialog(
          title: Text('Open Link'),
          content: Text('Open $url?'),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(context, false),
              child: Text('Cancel'),
            ),
            TextButton(
              onPressed: () => Navigator.pop(context, true),
              child: Text('Open'),
            ),
          ],
        ),
      );
      
      if (shouldOpen == true) {
        await launchUrl(Uri.parse(url));
      }
    },
    forConversation: forConversation,
  );
}

Properties

PropertyTypeDescription
patternRegExp?Regex pattern to match URLs
messageBubbleTextStyleFunction?Custom style for URL text in bubbles
onSearchFunction?Callback when URL is detected
showLoadingIndicatorbool?Show loading indicator during processing

Complete Example

import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

class UrlFormatterExample extends StatefulWidget {
  const UrlFormatterExample({super.key});

  @override
  State<UrlFormatterExample> createState() => _UrlFormatterExampleState();
}

class _UrlFormatterExampleState extends State<UrlFormatterExample> {
  User? chatUser;

  @override
  void initState() {
    super.initState();
    CometChat.getUser("uid").then((user) {
      setState(() => chatUser = user);
    });
  }

  @override
  Widget build(BuildContext context) {
    if (chatUser == null) {
      return const Center(child: CircularProgressIndicator());
    }

    return Scaffold(
      body: CometChatMessageList(
        user: chatUser,
        textFormatters: [
          CometChatUrlFormatter(
            messageBubbleTextStyle: (context, alignment, {forConversation}) {
              return TextStyle(
                color: alignment == BubbleAlignment.right 
                  ? Colors.white 
                  : Colors.blue,
                decoration: TextDecoration.underline,
              );
            },
          ),
          CometChatMentionsFormatter(),
        ],
      ),
    );
  }
}

Next Steps