在 Flutter 中初始化时带有错误表情符号的文本小部件
Text widget with wrong emoji on initialization in Flutter
我想使用 Flutter 在文本小部件中显示表情符号。
当我从互联网上复制示例表情符号时,其中一些在我的 IDE 中显示为 2 个字符。
例如:
static String dualCharEmoji = "⚔️";
static String singleCharEmoji = "";
当我在文本小部件中使用这个变量时,它们都工作正常:
Text("⚔️",)
Text("",)
但是,仅当第一个 运行 应用程序 时,双字符表情符号仅显示为它的第一个字符。
即只有在第一次打开应用程序时,剑图标显示为 ⚔
而不是 ⚔️
重新加载后它得到修复,并且热 reloading/hot 重新启动不会使其再次出现错误。
我的问题是:
这是一个错误吗?我在这里遗漏了一些细节吗?为什么只在第一次打开应用时出现?
如何从一开始就显示 2 倍大小的表情符号?
我正在使用以下 Flutter 版本:
>flutter --version
Flutter 1.9.1+hotfix.4 • channel stable • https://github.com/flutter/flutter.git
Framework • revision cc949a8e8b (9 weeks ago) • 2019-09-27 15:04:59 -0700
Engine • revision b863200c37
Tools • Dart 2.5.0
请参阅下面的最小可重现示例:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static String dualCharEmoji = "⚔️";
static String singleCharEmoji = "";
String text = dualCharEmoji;
int count = 0;
void swapText() {
setState(() {
if (count % 2 == 0)
text = singleCharEmoji;
else
text = dualCharEmoji;
count++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
text,
style: TextStyle(fontSize: 50),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: swapText,
),
);
}
}
在创建这个问题后,进行了多次不成功的尝试,并且没有 有效的答案,我在 Flutter 的官方 Github 存储库上创建了一个 issue。
在我展示我的问题后,一位用户解释说这是一个与 Flutter 如何渲染和缓存字体有关的错误,以防默认字体无法正确处理某些字符:
The first time that dualCharEmoji is rendered Flutter sees that the default font does not handle the 2694 character. [...]it can render the basic 2694 crossed swords character but not the 2694 FE0F emoji.
When singleCharEmoji is rendered Flutter now includes the NotoSansSymbols font in the list of fonts given to the HarfBuzz text shaper.[...] and matchFamilyStyleCharacter returns NotoColorEmoji. Flutter also adds this font to the cache.
The next time the engine tries to render dualCharEmoji it provides both cached fonts (NotoSansSymbols and NotoColorEmoji) to HarfBuzz. Now that HarfBuzz is aware of the sequences defined in NotoColorEmoji it can recognize the 2694 FE0F emoji and return it to Flutter.
我在这里只引用了讨论的一部分。您可以在我上面链接的问题页面上阅读完整的讨论和解释。
用户提出了一些解决方法,即两个:
首先,您可以强制引擎预缓存能够正确处理表情符号的字体。您可以通过在 build
或 initState
方法(在构建文本小部件之前运行的任何地方)中添加以下代码来完成此操作:
import 'dart:ui';
ParagraphBuilder pb = ParagraphBuilder(ParagraphStyle(locale: window.locale));
pb.addText('\ud83d\ude01'); // smiley face emoji
pb.build().layout(ParagraphConstraints(width: 100));
这适用于我的示例项目,但如问题页面所述:
However, this relies on implementation details of the current Flutter text engine that may change in the future.
因此请注意,此解决方法可能会在任何给定时间停止工作。
第二种解决方法如下:
For now the work around is to list the desired font in the text style and it will be resolved correctly.
这只是将 TextStyle
属性 设置为 fontFamily
(或 fontFamilyFallback
)属性 设置的文本小部件。所选字体必须已经支持所需的所有字符。这也适用于我,但是我必须从我的计算机(或来自 public 在线包)中包含自定义字体。
我想使用 Flutter 在文本小部件中显示表情符号。
当我从互联网上复制示例表情符号时,其中一些在我的 IDE 中显示为 2 个字符。
例如:
static String dualCharEmoji = "⚔️";
static String singleCharEmoji = "";
当我在文本小部件中使用这个变量时,它们都工作正常:
Text("⚔️",)
Text("",)
但是,仅当第一个 运行 应用程序 时,双字符表情符号仅显示为它的第一个字符。
即只有在第一次打开应用程序时,剑图标显示为 ⚔
而不是 ⚔️
重新加载后它得到修复,并且热 reloading/hot 重新启动不会使其再次出现错误。
我的问题是:
这是一个错误吗?我在这里遗漏了一些细节吗?为什么只在第一次打开应用时出现?
如何从一开始就显示 2 倍大小的表情符号?
我正在使用以下 Flutter 版本:
>flutter --version
Flutter 1.9.1+hotfix.4 • channel stable • https://github.com/flutter/flutter.git
Framework • revision cc949a8e8b (9 weeks ago) • 2019-09-27 15:04:59 -0700
Engine • revision b863200c37
Tools • Dart 2.5.0
请参阅下面的最小可重现示例:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static String dualCharEmoji = "⚔️";
static String singleCharEmoji = "";
String text = dualCharEmoji;
int count = 0;
void swapText() {
setState(() {
if (count % 2 == 0)
text = singleCharEmoji;
else
text = dualCharEmoji;
count++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
text,
style: TextStyle(fontSize: 50),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: swapText,
),
);
}
}
在创建这个问题后,进行了多次不成功的尝试,并且没有 有效的答案,我在 Flutter 的官方 Github 存储库上创建了一个 issue。
在我展示我的问题后,一位用户解释说这是一个与 Flutter 如何渲染和缓存字体有关的错误,以防默认字体无法正确处理某些字符:
The first time that dualCharEmoji is rendered Flutter sees that the default font does not handle the 2694 character. [...]it can render the basic 2694 crossed swords character but not the 2694 FE0F emoji.
When singleCharEmoji is rendered Flutter now includes the NotoSansSymbols font in the list of fonts given to the HarfBuzz text shaper.[...] and matchFamilyStyleCharacter returns NotoColorEmoji. Flutter also adds this font to the cache.
The next time the engine tries to render dualCharEmoji it provides both cached fonts (NotoSansSymbols and NotoColorEmoji) to HarfBuzz. Now that HarfBuzz is aware of the sequences defined in NotoColorEmoji it can recognize the 2694 FE0F emoji and return it to Flutter.
我在这里只引用了讨论的一部分。您可以在我上面链接的问题页面上阅读完整的讨论和解释。
用户提出了一些解决方法,即两个:
首先,您可以强制引擎预缓存能够正确处理表情符号的字体。您可以通过在 build
或 initState
方法(在构建文本小部件之前运行的任何地方)中添加以下代码来完成此操作:
import 'dart:ui';
ParagraphBuilder pb = ParagraphBuilder(ParagraphStyle(locale: window.locale));
pb.addText('\ud83d\ude01'); // smiley face emoji
pb.build().layout(ParagraphConstraints(width: 100));
这适用于我的示例项目,但如问题页面所述:
However, this relies on implementation details of the current Flutter text engine that may change in the future.
因此请注意,此解决方法可能会在任何给定时间停止工作。
第二种解决方法如下:
For now the work around is to list the desired font in the text style and it will be resolved correctly.
这只是将 TextStyle
属性 设置为 fontFamily
(或 fontFamilyFallback
)属性 设置的文本小部件。所选字体必须已经支持所需的所有字符。这也适用于我,但是我必须从我的计算机(或来自 public 在线包)中包含自定义字体。