作者:帅哥刘常胜 | 来源:互联网 | 2023-02-05 08:56
理论上Android是可以显示所有Unicode字符的,显示所有的汉字(目前Unicode里有8万多个东亚汉字)、emoji当然也没问题。Unicode值在0xFFFF以下的汉字已
理论上安卓是可以显示所有Unicode字符的,显示所有的汉字(目前Unicode里有8万多个东亚汉字)、emoji当然也没问题。
Unicode值在0xFFFF以下的汉字早已被广泛支持,所以本文不把它们看作生僻字。这里共有2万多个简体、繁体汉字。
本文说的生僻字是指Unicode值在0xFFFF以上的汉字,emoji也在这个范围里。这个范围也叫non-BMP。
可以看这篇文章了解汉字的大致分布。
主要有三个关键点:
1、确保字符集能覆盖生僻字。也就是在文件、数据库保存字符串时使用的字符集,应该是:GB18030、UTF-16、UTF-32等能支持所有Unicdoe字符的字符集。
误区a:如果使用GB2312或GBK字符集,它们的范围有限,生僻字没有被包含在内。
误区b:UTF-8编码在理论上也支持所有Unicode字符,但是Android的UTF-8解码器似乎有问题,只能支持一部分范围的常用字符,见此帖。(此条尚未验证,仅供参考)
2、String在处理生僻字时会使用surrogate对。
Java程序的String使用的是UTF-16编码。String的一个char占两个字节,能表示0~0xFFFF之间的数值范围。
于是在String里,常用字符(Unicode值小于等于0xFFFF)用一个char表示,剩下的字符(Unicode值大于0xFFFF)用两个char组合表示,这两个char叫surrogate对儿。所以我们的生僻字符须要用两个char组合表示。
surrogate对的原理是:两个char各有一个保留区域,这个保留区域有1024个位置,于是1024x1024大约等于104万,再加上单个char包含的字符,正好能覆盖Unicode所有的110多万个位置点。
这个不需要我们操心,只要记住String的length()函数的返回值可能大于实际字符数就可以了,想知道String的实际字符数可以用codePointCount()函数。同理,charAt()等基于char操作的函数可能也不再适用。
3、使用支持生僻字的字体。
就算程序内在支持生僻字,字体不支持也显示不出来。包括默认字体在内的很多字体都不支持生僻字。
我们可以找一个支持生僻字的字体,然后放到程序的资源目录里,指定使用它而不是系统的默认字体。打包了字体的程序会大很多,这也是没有办法的事。
链接a:一个支持所有汉字的字体,帖子,网盘。
链接b:在程序里使用指定字体的办法见此文的方法二。
Android上显示生僻字、emoji的办法