Flutter custom chat emoji text (custom icon text font)
import 'package:nft/services/safety/base_stateful.dart'; | |
import 'package:flutter/material.dart'; | |
/// Use | |
/// const WChatText(text: 'hello:heart.86ac068::smile.48f82f2::fire.9f77c64:'), | |
class WChatText extends StatefulWidget { | |
const WChatText({Key key, @required this.text}) : super(key: key); | |
final String text; | |
@override | |
_WChatTextState createState() => _WChatTextState(); | |
} | |
class _WChatTextState extends BaseStateful<WChatText> { | |
@override | |
Widget build(BuildContext context) { | |
super.build(context); | |
return Container( | |
child: RichText( | |
text: _buildEmojiTextSpan(_standardizeText(widget.text)), | |
), | |
); | |
} | |
// Standardize text | |
// hello:heart.86ac068::smile.48f82f2::fire.9f77c64: | |
// => | |
// hello\ue901\ue902\ue900 | |
String _standardizeText(String text) { | |
text = text?.replaceAll(RegExp(r':fire.\w+:'), '\ue900'); | |
text = text?.replaceAll(RegExp(r':heart.\w+:'), '\ue901'); | |
text = text?.replaceAll(RegExp(r':smile.\w+:'), '\ue902'); | |
return text; | |
} | |
// Get emoji color from code | |
Color _getEmojiColor(int emojiCode) { | |
switch (emojiCode) { | |
case 0xe900: | |
return const Color(0xFFFFD243); | |
case 0xe901: | |
return const Color(0xFFFF39AF); | |
case 0xe902: | |
return const Color(0xFF2CD7FF); | |
} | |
return null; | |
} | |
// Build text span | |
TextSpan _buildEmojiTextSpan(String text) { | |
if (text == null) { | |
return const TextSpan(); | |
} | |
final List<TextSpan> children = <TextSpan>[]; | |
// integer Unicode code points | |
final Runes runes = text.runes; | |
final List<int> chunk = <int>[]; | |
for (int i = 0; i < runes.length; i++) { | |
final int code = runes.elementAt(i); | |
// print('code ${code.toRadixString(16)}'); | |
// we assume that everything that is not | |
// in Extended-ASCII set is an emoji... | |
final bool isEmoji = code > 255; | |
if (!isEmoji) { | |
chunk.add(code); | |
} | |
if (isEmoji || i == runes.length - 1) { | |
children.add( | |
TextSpan( | |
text: String.fromCharCodes(chunk), | |
style: const TextStyle(), | |
), | |
); | |
chunk.clear(); | |
if (isEmoji) { | |
children.add( | |
TextSpan( | |
text: String.fromCharCode(code), | |
style: TextStyle( | |
fontFamily: 'nft', | |
color: _getEmojiColor(code), | |
), | |
), | |
); | |
} | |
} | |
} | |
return TextSpan(children: children); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment