Flutter中系统Emoji通过substring裁切无法识别、渲染错误
- 场景
- 分析/思考
- 寻找神马东西引起的渲染错误
- 为什么 substring 之后就无法显示了
- 结论
- 分析 substring
场景
- 在发布文章的时候,有标题和内容,标题可为空,在没有标题的情况下,截取部分内容当作标题。
- 内容列表显示的时候,某些特殊的情况下(并不重要),我们就需要裁切文章标题。
- 当文章标题中有文字 + 系统自带的 emoji 的时候,我们去裁切标题就会出现无法识别渲染出来乱码的情况。
如下:
import 'package:flutter/material.dart';
class SubStringSystemIcon extends StatefulWidget {
const SubStringSystemIcon({super.key});
State<SubStringSystemIcon> createState() => _SubStringSystemIconState();
}
class _SubStringSystemIconState extends State<SubStringSystemIcon> {
Widget build(BuildContext context) {
const iconString = '🌾🍁🍂🌺';
const textString = '系统表情';
return Scaffold(
appBar: AppBar(
title: const Text('字符串截取系统表情包出现错误问题'),
),
body: Center(
child: Column(
children: [
Text(
textString + iconString.substring(0, 3),
),
],
),
),
);
}
}
分析/思考
寻找神马东西引起的渲染错误
思考(1)
遇到渲染错误的情况我第一时间想到的是这个emoji识别不出来,导致的显示出错。
tip:在 Flutter 输入框中以苹果的数字图标 1 2 3 4 5 6 7 8 9 0 为开头的内容,输入到输入框中就会导致后续的所有字符都无法识别。
想要了解的可以看这个 Flutter issues 11517
然后我测试了这个文章的标题完全显示出来的情况下,会不会出现这种情况。
class _SubStringSystemIconState extends State<SubStringSystemIcon> {
Widget build(BuildContext context) {
const iconString = '🌾🍁🍂🌺';
const textString = '系统表情';
return Scaffold(
appBar: AppBar(
title: const Text('字符串截取系统表情包出现错误问题'),
),
body: Center(
child: Column(
children: [
Text(textString + iconString),
],
),
),
);
}
}
结果不是因为无法识别。在测试demo中显示全部标题是完全没有问题的,都可以显示。
思考(2)
全部显示没有问题,第一时间,我就想到了,是因为 substring 导致的错误。
我就试着打印出标题的全部长度后,一下子发现了问题的所在。
为什么 substring 之后就无法显示了
我们可以到我们打印的字符串的长度后会发现,每个 emoji 的长度是2
这样让我想到了,tips中提到的 issues,苹果的数字 emoji 长度是3
结论
一个emoji 的长度是2 或者 3,那么我们 substring 的时候,就会特殊情况下把emoji裁切了一半的情况。这样就会导致显示错误。
分析 substring
我们知道一个字符的长度是1,那么为什么emoji的字符长度不是1。
我试着打印出了他们的 unicode 发现了有意思的东西。
发现没有,emoji 是多个 unicode 的值组成(UTF-32格式)而 substring 裁切的的时候,识别每一个 unicode 值为一个字符。所以就出现了,某下情况下使用substring裁切带emoji的字符串的时候,就会出现渲染错误的问题。