【发布时间】:2017-12-09 17:07:07
【问题描述】:
我有一些包含表情符号的文本,我正在尝试在文本小部件上显示它们。但是,它们似乎显示为外来字符。 Flutter 是否支持显示表情符号?应该适用于 iOS 和 Android
【问题讨论】:
我有一些包含表情符号的文本,我正在尝试在文本小部件上显示它们。但是,它们似乎显示为外来字符。 Flutter 是否支持显示表情符号?应该适用于 iOS 和 Android
【问题讨论】:
到目前为止,不幸的是,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 支持表情符号。这是一些演示表情符号文本输入的代码。 (如果您看到外来字符,很可能您将字节解码为 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;
});
},
),
);
}
}
【讨论】:
您可以通过以下方式在文本字段中插入表情符号:
如果您使用的是 Mac,则可以按 Control + Command + Space。 Windows 用户可以点击“Windows 键”+; (分号)。
复制粘贴来自@Reso Coder 的指令 https://www.youtube.com/watch?v=KfuUkq2cLZU&t=15s
我在 mac 上测试过,它可以工作。
【讨论】:
如果您只想在文本小部件中包含表情符号,您可以从其他地方复制表情符号并将其粘贴到文本小部件中。 我使用GeteMoji 复制表情符号。
代码:见第 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
))));
}
【讨论】:
要获得完整的表情符号兼容性(至少在 android 中,并非所有表情符号在旧操作系统版本中都受支持),您可以在https://www.google.com/get/noto/#emoji-zsye-color 使用谷歌免费字体 Noto Color Emoji
fonts:
- family: NotoEmoji
fonts:
- asset: fonts/NotoColorEmoji.ttf
weight: 400
与文本样式一起使用
Text("?", TextStyle(fontFamily: 'NotoEmoji'))
【讨论】:
当表情符号未显示时,问题很可能是您使用的字体。
在尝试表情符号字体包之前,您可以给文本字段一个空字符串作为 fontFamily 或尝试使用 Flutter 打包的默认字体选项。 这将防止添加不需要的依赖项。
例如,这个表情符号在 android 上没有显示,'Product Sans' 作为 fontFamily,我只是为文本字段添加了一个空字符串和字体系列,这就解决了这个问题。
Text('₦', TextStyle(fontFamily: ''))
【讨论】:
您可以轻松使用 fontFamily 作为样式来解决问题 我和包一起用过
auto_size_text: ^2.1.0
AutoSizeText(
lesson.FullExercise,
textAlign: TextAlign.justify,
style:TextStyle(
fontFamily: 'EmojiOne',
),
),
请注意 如果要在 MySQL 中存储数据并且文本包含 Emoji,则需要将文本的集合更改为 utf8mb4
【讨论】: