最近在用Flutter开发一个生成推文图片的app —— Cardit,发现Dart在处理包含emoji的字符串时有些问题,主要是一个emoji的长度并不是1,所以在做类似substring的操作时很麻烦。
探索字符串长度
Dart中的String是以UTF-16编码的,已经可以表示绝大部分语言的文字了,包括中文,比如:
1 | print('hello'.length); // 5 |
所以在处理中文时不用担心,就跟普通拉丁文字一样。而当出现emoji时,情况就不对了:
1 | print('🍎'.length); // 2 |
这种情况要去做字符串截取是很麻烦的,好在虽然Dart foundation中不提供这个能力,但提供了官方的Characters package来处理这种情形。
Characters package
Flutter中已经默认引入了Characters,可直接使用;如果是纯Dart项目则需要import(不用在pubspec.yaml
中申明):
1 | import 'package:characters/characters.dart'; |
这样长度就正常了:
1 | print('🍎'.characters.length); // 1 |
相当于处理String时先转成Characters再处理,而上面的characters
,其实是String的一个extension方法:
1 | import 'characters.dart'; |
substrings
最后回到最初的问题,如何像普通String一样处理substring。简单说,使用getRange(int start, [int? end])
对象就可以了,与String.substring()
用法几乎一致。
1 | String str = '🇭🇺👨👩👧🍎abc'; |
而Characters.toString()
就可以把Characters转化回String对象了。