Displaying text with Emojis on Flutter

The Problem

As of now, unfortunately, Flutter uses the default Emojis supported on a given platform. Therefore, when building a cross-platform app you may face issues of Emojis showing on certain devices and not on others.

The Solution

The solution I settled for is to use a custom Emoji font such as Emoji One and RichText widget instead of the basic Text widget.

With this, you can simply have:

RichText(
  text: TextSpan(
    children: <TextSpan>[
      TextSpan(
        text: 'Hello',  // non-emoji characters
      ),
      TextSpan(
        text: '🧭 🏳️\u200d🌈', // emoji characters
        style: TextStyle(
          fontFamily: 'EmojiOne',
        ),
      ),
    ],
  ),
);

Generalized Solution

With this idea, we can even create a custom widget that given a string, builds a RichText object with all the TextSpans autocreated:

class EmojiText extends StatelessWidget {

  const EmojiText({
    Key key,
    @required this.text,
  }) : assert(text != null),
       super(key: key);

  final String text;

  @override
  Widget build(BuildContext context) {
    return RichText(
      text: _buildText(this.text),
    );
  }

  TextSpan _buildText(String text) {
    final children = <TextSpan>[]; 
    final runes = text.runes;

    for (int i = 0; i < runes.length; /* empty */ ) {
      int current = runes.elementAt(i);

      // we assume that everything that is not
      // in Extended-ASCII set is an emoji...
      final isEmoji = current > 255;
      final shouldBreak = isEmoji
        ? (x) => x <= 255 
        : (x) => x > 255;

      final chunk = <int>[];
      while (! shouldBreak(current)) {
        chunk.add(current);
        if (++i >= runes.length) break;
        current = runes.elementAt(i);
      }

      children.add(
        TextSpan(
          text: String.fromCharCodes(chunk),
          style: TextStyle(
            fontFamily: isEmoji ? 'EmojiOne' : null,
          ),
        ),
      );
    }

    return TextSpan(children: children);
  } 
} 

Which can be used as:

EmojiText(text: 'Hello there: 🧭 🏳️\u200d🌈');

This has the advantage of having the consistent support of Emojis on your app that you can control on different platforms.

The downside is that it will add some MBs to your app.

Leave a Comment