在 Flutter 上显示带有表情符号的文本

Posted

技术标签:

【中文标题】在 Flutter 上显示带有表情符号的文本【英文标题】:Displaying text with Emojis on Flutter 【发布时间】:2017-12-09 17:07:07 【问题描述】:

我有一些包含表情符号的文本,我正在尝试在文本小部件上显示它们。但是,它们似乎显示为外来字符。 Flutter 是否支持显示表情符号?应该适用于 iosandroid

【问题讨论】:

【参考方案1】:

问题

到目前为止,不幸的是,Flutter 使用给定平台上支持的默认表情符号。因此,在构建跨平台应用时,您可能会遇到表情符号在某些设备上显示而不在其他设备上显示的问题。

解决方案

我确定的解决方案是使用自定义表情符号字体,例如 Emoji One 和 RichText 小部件,而不是基本的 Text 小部件。

有了这个,你可以简单地拥有:

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

广义解

有了这个想法,我们甚至可以创建一个自定义小部件,给定一个字符串,构建一个 RichText 对象,并自动创建所有 TextSpans:

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);
   
 

可以用作:

EmojiText(text: 'Hello there: ? ?️\u200d?');

这样做的好处是在您的应用上始终支持表情符号,您可以在不同平台上进行控制。

缺点是它会给你的应用添加一些MBs

【讨论】:

这是在 Flutter 中将表情符号集成到文本中最完整的解决方案,坦克! Emoji One 似乎已成为一项名为 JoyPixels 的付费服务。我正在考虑使用上述解决方案使用 Google 的开源 Apache License 字体。字体名为 Noto Emoji github.com/googlefonts/noto-emoji 这太棒了,你应该用它做一个图书馆! 您知道如何在 TextField 而不是 Text 上执行此操作吗?【参考方案2】:

Flutter 支持表情符号。这是一些演示表情符号文本输入的代码。 (如果您看到外来字符,很可能您将字节解码为 ASCII 而不是 UTF-8;如果您使用演示问题的代码更新您的问题,我们可以向您展示如何解决此问题。)

import 'dart:async';
import 'package:flutter/material.dart';

void main() 
  runApp(new MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyHomePage(),
    );
  


class MyHomePage extends StatefulWidget 
  MyHomePage(Key key) : super(key: key);

  @override
  _MyHomePageState createState() => new _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 
  String _message = '?';

  Future<String> _promptForString(String label,  String hintText ) 
    final TextEditingController controller = new TextEditingController();
    return showDialog(
      context: context,
      child: new AlertDialog(
        title: new Text(label),
        content: new TextFormField(
          controller: controller,
          decoration: new InputDecoration(hintText: hintText),
        ),
        actions: <Widget>[
          new FlatButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('CANCEL'),
          ),
          new FlatButton(
            onPressed: () => Navigator.pop(context, controller.text),
            child: const Text('OK'),
          ),
        ],
      ),
    );
  

  @override
  Widget build(BuildContext context) 
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(_message),
      ),
      body: new Center(
        child: new Text(_message, style: Theme.of(context).textTheme.display2),
      ),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.edit),
        onPressed: () async 
          String message = await _promptForString('New text', hintText: 'Try emoji!');
          if (!mounted)
            return;
          setState(() 
            _message = message;
          );
        ,
      ),
    );
  

【讨论】:

有没有办法在 Flutter 中显示专用的表情符号屏幕?我不是指集成在键盘中的表情符号。 @colin-jackson 在 iOS 上标记表情符号无法使用您上面的代码。所有其他表情符号的作品。我正在构建的颤振应用程序需要标志表情符号。有任何想法吗?这是 unicode/utf-8 解码问题吗? 似乎为此提交了一个错误:github.com/flutter/flutter/issues/16960。点赞该错误以帮助确定优先级:) 顺便说一句:作为不涉及键盘输入的用例的解决方法,使用pub.dartlang.org/packages/country_icons 可能很有用 我在哪里可以获得这些 whatsapp 之类的表情符号?【参考方案3】:

您可以通过以下方式在文本字段中插入表情符号:

如果您使用的是 Mac,则可以按 Control + Command + Space。 Windows 用户可以点击“Windows 键”+; (分号)。

复制粘贴来自@Reso Coder 的指令 https://www.youtube.com/watch?v=KfuUkq2cLZU&t=15s

我在 mac 上测试过,它可以工作。

【讨论】:

我刚刚发布了我的答案,然后我找到了你的:) 对我来说实际上是“赢”+“。”在窗户上【参考方案4】:

如果您只想在文本小部件中包含表情符号,您可以从其他地方复制表情符号并将其粘贴到文本小部件中。 我使用GeteMoji 复制表情符号。

See the Output Screenshot

代码:见第 8 行。

Widget build(BuildContext context) 
    return Center(
        child: Container(
            alignment: Alignment.center,
            color: Colors.deepPurple,
            //width: 200.0,
            //height: 100.0,
            child: Text("Emoji ? ",
                style: TextStyle(
                  fontFamily: 'Raleway',
                  fontSize: 40,
                  decoration: TextDecoration.none,
                  color: Colors.white

                ))));
  

【讨论】:

【参考方案5】:

要获得完整的表情符号兼容性(至少在 android 中,并非所有表情符号在旧操作系统版本中都受支持),您可以在https://www.google.com/get/noto/#emoji-zsye-color 使用谷歌免费字体 Noto Color Emoji

将其添加到字体文件夹中 添加 pubspec.yaml
    fonts:
    - family: NotoEmoji
      fonts:
        - asset: fonts/NotoColorEmoji.ttf
          weight: 400

与文本样式一起使用

Text("?", TextStyle(fontFamily: 'NotoEmoji'))

【讨论】:

这在最新的 Flutter 和 ios sim 中有效吗?在 iPhone 8 模拟器上使用 ios13.2 时,我收到一条消息崩溃:[VERBOSE-2:FontFamily.cpp(184)] 无法获取 cmap 表大小! [VERBOSE-3:FontCollection.cpp(95)] nTypefaces == 0 我发现该字体与 iOS 或 MacOS 不兼容,并且由于 Apple 不允许我们在游戏中使用他们的表情符号作为精灵,我需要找到另一种不错的表情符号字体。【参考方案6】:

当表情符号未显示时,问题很可能是您使用的字体。

在尝试表情符号字体包之前,您可以给文本字段一个空字符串作为 fontFamily 或尝试使用 Flutter 打包的默认字体选项。 这将防止添加不需要的依赖项。

例如,这个表情符号在 android 上没有显示,'Product Sans' 作为 fontFamily,我只是为文本字段添加了一个空字符串和字体系列,这就解决了这个问题。

Text('₦', TextStyle(fontFamily: ''))

【讨论】:

【参考方案7】:

您可以轻松使用 fontFamily 作为样式来解决问题 我和包一起用过

auto_size_text: ^2.1.0

AutoSizeText(
              lesson.FullExercise,
              textAlign: TextAlign.justify,
              style:TextStyle(
              fontFamily: 'EmojiOne',
              ),
            ),

请注意 如果要在 mysql 中存储数据并且文本包含 Emoji,则需要将文本的集合更改为 utf8mb4

【讨论】:

以上是关于在 Flutter 上显示带有表情符号的文本的主要内容,如果未能解决你的问题,请参考以下文章

带有动画表情符号的 Discord 机器人

带有 gif 和表情符号以及图像 Java 的聊天室

nodejs discord bot - 带有由表情符号分隔的单词的消息

带有自定义表情符号的反应角色

带有 android 4.4 的谷歌键盘中的默认表情符号按钮

如何在其他设备上显示我的键盘扩展的表情符号