安卓5.0+是可以显示所有(8万多个)Unicode汉字的,本文介绍显示生僻汉字的方法,这个方法也适用于其它特殊字符。
Unicode值在0xFFFF以下的(2万多个简体、繁体)汉字早已被广泛支持,所以本文不把它们看作生僻字。
本文说的生僻字是指Unicode值在0xFFFF以上的汉字,这个范围也叫non-BMP。
可以看这篇文章了解汉字的大致分布。
主要有4个关键点:
一、需使用Android 5.0以上系统。
经过我的测试,在Android 4.3.1模拟器、4.4.2模拟器上会出现问题,而在Android 5.0.2模拟器、6.0真机、7.0模拟器上正常。
问题见本文最后部分的两张截图:附1、附2。
二、确保字符集能覆盖生僻字。
也就是在文件、数据库保存字符串时使用的字符集,应该是:GB18030、UTF-8、UTF-16、UTF-32等能支持所有Unicode字符的字符集。
注意a:不要使用GB2312、GBK或BIG5字符集,它们的范围有限,都不支持生僻字(Unicode值大于0xFFFF)。
注意b:不要在Android程序的配置xml文件里写生僻字,Android在用UTF-8解码这些xml时,支持的范围并不完整。这个bug在Android 6.0里被修复。见此帖。
按如下方法把字符串读入String后,我们进入下一个关键点。
byte[] b = read_bytes_from_somewhere();
String str = new String(b, "GB18030");
三、String在处理生僻字时会使用surrogate对。
Java的String使用的是UTF-16编码。String的一个char占两个字节,能表示0~0xFFFF之间的数值范围。
于是,根据UTF-16的规则,在String里:常用字符(Unicode值小于等于0xFFFF)用一个char表示;剩下的字符(Unicode值大于0xFFFF)用两个char组合表示,这两个char叫surrogate对儿。所以我们的生僻字符须要用两个char组合表示。
surrogate对的原理是:两个char各有一个保留区域,这个保留区域有1,024个位置,于是1,024x1,024等于1,048,576,再加上单个char包含的字符,正好能覆盖Unicode所有的1,114,112个位置点。
在这里,搞清楚两个概念就可以了:
char,一个char就是一个两字节整数。它是String的最小单位,一个String包含0个或若干个char。String对象的length()函数返回的就是char的个数。
code point,一个code point就是一个Unicode字符,一个实际的字符。在String里,它可能用1个char表示,也可能用2个char组合表示,没有第三种可能。
所以,在处理生僻字时,String的length()函数的返回值可能大于实际字符数,想知道String的实际字符数可以用codePointCount()函数。同理,charAt()等基于char操作的函数可能也不再适用。
四、使用支持生僻字的字体。
就算程序内在支持生僻字,字体不支持也显示不出来。包括默认字体在内的很多字体都不支持生僻字。
我们可以找一个支持生僻字的字体,然后放到程序的资源目录里,指定程序使用它而不是系统的默认字体。
先找一个支持生僻字的字体,比如这个开心宋体:帖子,网盘。
然后按以下方法使用该字体就可以了(出处):
//得到TextView控件对象
TextView textView = (TextView) findViewById(R.id.custom);
//将字体文件保存在assets/fonts/目录下,创建Typeface对象
Typeface typeFace = Typeface.createFromAsset(getAssets(), "fonts/KaiXinSong.ttf");
//使用字体
textView.setTypeface(typeFace);
注意a:打包了字体的程序会大很多,这也是没有办法的事。除非做成按需下载字体,这就依赖网络了;或者生成一个只包含所需汉字的字体文件。(2017年发布的Android Support Library v26增强了对字体的支持,见此视频。)
注意b:各字体可能会有自己的侧重点,比如支持生僻汉字的字体可能不支持emoji,支持emoji的字体可能不支持生僻汉字。
注意c:可以用SpannableString为一个字符串的部分字符使用指定的字体,见为部分字符指定字体、在SpannableString使用指定字体。
在按如上方法使用了开心宋体后,已经可以在Android 5.0.2模拟器上显示各区汉字:
在Android 5.0.2模拟器上默认字体的效果,可以看到CJK统一汉字扩展B、C、D、E区的汉字都无法显示:
附1,在Android 4.4.2模拟器上,使用开心宋体后,常用字反倒显示不出来了。
在4.3.1、4.4.2上,使用Simsun-ExtB字体也有类似情况,所以这应该是安卓4.x的问题。
难道是系统不支持多于65536个字符的字体?我没有去验证,仅仅是猜测。
附2,在Android 4.4.2模拟器上,使用默认字体的效果:
关于Unity程序在IOS和Android上显示内嵌网页的方式
近期因为有须要在Unity程序执行在ios或android手机上显示内嵌网页.所以遍从网上搜集了一下相关的资料.整理例如以下: UnityWebCore 从搜索中先看到了这个.下载下来了以后发现这个的 ...
JS文件中的中文在网页上显示为乱码解决方法
转自:http://www.pc6.com/infoview/Article_63835.html 如果JS文件中的中文在网页上显示为乱码,不妨采用本文章中的方法来试一试,或许能解决使你很头疼的问题. ...
HTML让文字在图片上显示的几种方法
第一种方式是image 作为背景图片,即:background:url("......."); 第二种方式是将img块与文字块(文字块采用span标签显示)放在同一个div 中,然 ...
日期在苹果手机上显示NaN的处理方法
注意两点即可: 1.苹果只认识 yyyy/mmmm/dddd/ 这类格式的日期 2.如果输出后还要进行处理日期对比,苹果默认会带中文字,如:年月日,需要转成上面1当中的日期格式在转时间戳进行比较 G ...
在远程X server上显示图形的设置方法
1.在服务器的/etc/ssh/sshd_config中,设置X11Forwarding yes,然后重启ssh服务,cd /etc/init.d这个目录下执行 ./ssh restart 2.在客户 ...
unity,将camera设为don't clear在android上会显示不正常
将camera设置为don't clear,在pc和ios上显示没问题,但在android上显示不正常,改为only depth可以.
教你用PS制作雨天窗户上透明水滴字
雨天窗户上透明水滴字制作方法很简单,主要利用图层样式来实现.学习后可以让你对图层样式有更好的了解,认识. 先看下完成后的效果图: 步骤1: 在Photoshop中我们新建或Ctrl+N,创建1920x ...
利用SQLite在android上实现增删改查
利用SQLite在android上实现增删改查 方法: 一.直接利用database.execSQL()方法输入完整sql语句进行操作 这种方法适用于复杂的sql语句,比如多表查询等等 这里适合于增删 ...
Android上的MVP:如何组织显示层的内容
MVP(Model View Presenter)模式是著名的MVC(Model View Controller)模式的一个演化版本,目前它在Android应用开发中越来越重要了,大家也都在讨论关于M ...
随机推荐
Bash 里的转义序列
在 Bash 里,一共有五个地方支持反斜杠开头的转义序列,包括两个内部命令 echo 和 printf 的参数里,字符串语法 $'...' 里,还有四个提示符变量 PS1-PS4 里,以及在 Read ...
CSS 去除列表项li前面的小圆点
前言 在默认的情况下,浏览器会在
标签前面加上小圆点形成列表项,如下所示使用- 项1 项2 项3 或者使用
- 项1 项2 项3 这在有时候确实给我 ...
CheckBox的触发
遇到的问题:当Checkbox选中时触发Checked事件,使界面处于状态1,但是页面状态2时也希望checkBox处于选中状态,但是直接修改它的IsChecked属性势必会触发他的Checked事件 ...
Clementine 12.0 的使用安装(数据挖掘)
1.下载[统计数据挖掘工具].TLF-SOFT-SPSS_Clementine_v12.0-CYGiSO.bin 2.下载虚拟光驱安装软件 本人使用的是DTLite4402-0131. 3.如果需要汉 ...
ASP.NET WEB API构建基于REST风格