了解 Unicode 在 Flutter 上的展示

image

以前我对 emoji 是一头雾水,尤其是接入微信登录时,对于名字带表情的都是简单过滤处理,很暴力不是,我也试了好几次像支持 emoji,单奈何就是不行,今天看到了有关文章,总结了下,总算是清楚了,去了我一块心病,对于 emoji 不清楚的同学可以试试看,也许对你有帮助

emoji 其实就是 Unicode 16进制编码~


Unicode 简介

Unicode 编码是国际最通用的字符编码了,Unicode 里给不同语言的每个字符,其他各种符号,包括 emoji 表情都设置有自己独立的编号,所以就不会再出现乱的问题了,但是随着各种符号越来越多,尤其是 emoji 表情大行其道之后,这符号的数量与日俱增,为了装的下这么多符号,目前 Unicode 最多已经采用到 32位来存储了

  • UTF-8 - 占用一到四个字节,主要用来存储英文系字符
  • UTF-16 - 占用二或四个字节,主要存储世界上所有文字
  • UTF-32 - 占用四个字节,主要方 emoji 表情这种

UTF 有好几种,不是说只用最大编码的,不同的系统根据实际需求会选择自己默认支持的 UTF,一般文字的话 UTF-8 就足够了,但是处理 emoji 就得 UTF-32 了,具体在于使用场景


Unicode 储存图

UTF-32 储存值从 U+0000U+10FFFF,分成14个扇区存储,每一个扇区有 256 个小块,每个小块有 16×16 = 256 个编码点,总体下来每个扇区有 65536 个 编码点

扇区图:没一个大块就是一个扇区


image

不同语言的字符,包括古今文字,上古语言,符号,emoji 都存储在不同的扇区内

  • Unicode 0 号平面(0000-FFFF)
  • Unicode 1 号平面(10000-1FFFF)

Unicode 所有的字符可以在官方网站上查询到:

所以这 Unicode 数值也挺乱的,大家要注意,对于不同的数值范围 Dart 中有不同的保存格式:

  • \u2665 - 4个16进制的数的这么写
  • \u{1f600} - 但要不是4位的就得在数值前加{}

Flutter 上显示 emoji

Flutter 上想要正确显示 emoji 表情,请示就是给不同数值范围的 Unicode 编码套整个的格式

显示单个 emoji

var index = "\u{1f44f}";
image

显示多个,带文字混排

Runes input = new Runes(
  '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d} 哇哈哈哈哈!!!');
var index = String.fromCharCodes(input);
image

Dart 字符编码的 API

Dart 上又一个接受 UTF-32 编码的类:Runes,可以把 UTF-32 处理成能是别的 10进制数据

Dart 文字显示默认是 UTF-16 的,我们兼容 emoji 的话最好用 UTF-32,必须用 Runes 这个类,Runes 可以让我们按照 UTF-32 存储展示字符

dart:core 库提供了获取字符编码的 API:

  • String.codeUnitAt(index) - 返回指定字符的 10 进制 Unicode 索引
  • String.codeUnits - 返回所有字符的 10 进制 Unicode 索引,结果是个集合
  • String.runes - 返回所有字符的 10 进制 Unicode 编码值,结果是个集合
var index1 = "我";
var index2 = "我是富翁,我老有钱了";

print("index1:${index1.codeUnitAt(0)}");
print("index1:${index2.codeUnits}");
print("index1:${index1.runes}");
I/flutter ( 6849): index1:25105
I/flutter ( 6849): index1:[25105, 26159, 23500, 32705, 65292, 25105, 32769, 26377, 38065, 20102]
I/flutter ( 6849): index1:(25105)

我详细解释下,有点绕,不容易搞清楚


例子:

Unicode 编码都是 16 进制的,通常表示为 \uXXXX,其中这个 xxxx 就是具体的 16进制值

比如这个符号:他的 16进制 Unicode 编码是 \u2665,2665 的 10 进制 = 9829

image

我们来看下:

Runes input = new Runes('\u2665');
var index = String.fromCharCodes(input);
print("index1:${index.codeUnitAt(0)}");
print("index1:${index.codeUnits}");
print("index1:${index.runes}");
I/flutter ( 6849): index1:9829
I/flutter ( 6849): index1:[9829]
I/flutter ( 6849): index1:(9829)

拿到的结果正好对的上 10进制数值,我们转成 16进制加上 \u 就是 Unicode 编码了

  • 16 进制 Unicode 编码显示,使用 Runes 类包裹数据
Runes input = new Runes('\u2665');
var index = String.fromCharCodes(input);
  • 10 进制 就不用 Runes 了,直接走
var index = String.fromCharCode(9829);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 之前突然发现自己对字符编码还是一知半解,基本上只是听说过各种编码的名字,对它们之间的特点和区别还是不甚了解。所以这...
    L_Zephyr阅读 6,384评论 0 4
  • 1. ASCII   我们知道,计算机内部是通过二进制数据进行操作的,所有的信息最终都会转换为一个二进制值,二进制...
    骑着乌龟去看海阅读 5,728评论 0 4
  • 本文转自 微信公众号 jobbole 程序员世界对这个名字发自内心的恐惧和敬畏。我们都知道在我们的软件中应该 “支...
    faremax阅读 5,610评论 0 3
  • 某一天,leader找到我说,felix啊,这里有个小需求,给我们的实名认证中的地址加入字数限制,一天时间绰绰有余...
    felix9阅读 20,715评论 0 15
  • 今天做了几笔,前几笔都赚了,但是后来觉得要跌,买了几手空,结果被涨的连本金都赔进去了。
    jjhhkk阅读 1,706评论 0 1

友情链接更多精彩内容