守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 943|回复: 0

[技术资料] [转]NME Android目标中文输入问题完美解决!

[复制链接]
  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    51757
    钢镚
    1422

    开源英雄守望者

    发表于 2015-5-29 09:52:36 | 显示全部楼层 |阅读模式
    本帖最后由 破晓 于 2015-5-29 09:54 编辑

    最近研究了一下haxe,发现蛮牛逼的,转几篇知识帖



    haXe开发笔记:中文问题的小结
    * .hx源文件中如果包含中文,要保存成UTF-8编码才能够正确被haXe编译器解析,是否包含BOM(Byte Order Marker, 在UTF-8文件中,为EF BB BF三个字节的固定值)无所谓。
    * 采用Assets.getText()是可以正确载入包含中文的文本文件的,前提是文本文件要用UTF-8编码,另外UTF-8文本文件中不要包含BOM 否则在cpp等目标中,这个BOM也会被当做字符载入进来。
    * Flash目标和Cpp目标的运行时字符串编码是不同的,因此包含中文的字符串长度在不同的目标中并非一致,这个千万要引起注意!
    * Flash的运行时字符串编码应该是是Unicode,每个字符包括中文都是双字节,所以每个中文字符占1个长度;而windows/android等基于hxcpp的目标的内部编码则是ISO8859-1,因此Ascii字符占1个长度,而中文以UTF-8表示则占3个长度。也就是说:

    1. "haXe爱好者".length == 7; // flash
    2.   "haXe爱好者".length == 13; // cpp, android etc. (= 4 + 3 * 3)
    复制代码

    * 其实在cpp中想用GBK编码来表示中文也未尝不可,毕竟对中文来说GBK更节省内存。但如果想让TextField正确显示中文,则TextField.text属性中的中文必须是以UTF-8编码的,因此需要在调用前进行编码转换。
    * 经测试,在neko和windows目标中(中文WindowsXP),如希望用trace()在控制台正确输出中文,则传入的字符串必须以GBK编码。因此,在你的程序中,你到底用何种编码表示中文,就要看你自己的取舍了。当然,搞一个UTF-8 <-> GBK转换也并非太困难的事情。
    * 在Android手机中(小米实测),TextField如使用默认字体是显示不了中文的,因为从NME源代码分析,NME采用的默认字体是Times,并不包括中文。但可以在应用中自带中文TrueType字体,使用下面的方法来设置字体:
    1. var fontSize = 24, fontColor = 0xFF0000;
    2. myTextField.defaultTextFormat = new TextFormat(Assets.getFont("res/fangsong.ttf").fontName, fontSize, fontColor);
    3. myTextField.embedFonts = true;
    复制代码

    * 另外注意,经我测试,似乎TextField的text属性必须在defaultTextFormat属性之后进行赋值,否则自定义字体不生效。
    * 另外某些低端Android手机(比如我的华为C8500)可能无法正常载入中文字体,可能是因为内存不够?这就没有办法了。
    * 目前Neko目标在UI绘制中文暂时无解(也可能是我没找到),因此我暂时放弃neko了,改用windows目标代替。


    前面写了篇关于中文显示的文章,地址在:http://hi.baidu.com/rockswang/item/7a6e5c283eb1190f42634acb


    在Android平台上,上文给出的解决方案是应用自带中文字体。

    但是这里有个问题就是中文字体文件普遍太大了,比如我找的仿宋字体算小的了,也有4M左右,而微软雅黑居然要14M,这样apk安装包就很大了。另外,经测试我的华为C8500低端手机上无法正常载入嵌入字体,可能是内存不够。

    完美的解决方案当然就是使用Android的设备自带字体,但在以前的测试中,这似乎只对英文文本有效。

    经读取NME源代码以及无数次真机验证,今天终于解决了这个问题。

    方案的关键就在于:经研究,NME的Font类是可以访问本地文件系统中的字体的。而Android系统中的默认中文字体文件的路径是/system/fonts/DroidSansFallback.ttf。

    此方案经验证亦可工作于C8500低端手机,因此堪称完美!

    具体请看代码如下:

    1. var tf = new TextField();

    2. #if android

    3. var format = new TextFormat(new Font("/system/fonts/DroidSansFallback.ttf").fontName);

    4. #else

    5. var format = new TextFormat();

    6. #end

    7. format.color = 0xFF0000;

    8. format.size = 24;

    9. tf.defaultTextFormat = format;

    10. tf.text = "1234567890AbCdEfGh 看看:中文显示是否正常!m(^_*)[        DISCUZ_CODE_1        ]quot;;

    11. tf.height = 400;

    12. tf.width = 400;

    13. tf.multiline = true;

    14. tf.wordWrap = true;

    15. tf.selectable = false;

    16. tf.x = 20;

    17. tf.y = 30;

    18. canvas.addChild(tf);
    复制代码



    NME使用Android设备自带中文字体

    经验证,在Android/Windows等目标平台上(iOS目前没条件测试),中文输入还是不行,TextField似乎仅接受Ascii字符。


    今天在群中看到有位大侠找到了老外写的一篇文章解决了这个问题:

    于是特意测试了一下,上面老外的原版补丁未能解决一次输入多个字符的问题,但是稍作修改即可成功输入中文了,而且像讯飞输入法之类的语音大段输入也没问题!目前看来已经没有什么东西能阻挡haXe制霸移动开发的步伐了,哇哈哈哈哈!
    具体修改步骤如下:

    1. 这次需要hack NME的Android模板文件了,具体路径如下:

      <haXe安装目录>\lib\nme\<版本号>\tools\command-line\android\template\src\org\haxe\nme\MainView.java

    2. 在MainView类中添加一个方法如下:

    1.   @Override
    2.     public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
    3.         String s = event.getCharacters();
    4.         if (s == null || s.length() == 0) return super.onKeyMultiple(inKeyCode, repeatCount, event);
    5.         final char[] cc = s.toCharArray();
    6.         int cnt = 0;
    7.         for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0);
    8.         if (cnt == 0) return super.onKeyMultiple(inKeyCode, repeatCount, event);
    9.         final MainView me = this;
    10.         queueEvent(new Runnable() {
    11.             // This method will be called on the rendering thread:
    12.             public void run() {
    13.                 for (int i = 0, n = cc.length; i < n; i++) {
    14.                     int keyCode;
    15.                     if ((keyCode = cc[i]) != 0) {
    16.                         // Simulate key down and up...
    17.                         me.HandleResult(NME.onKeyChange(keyCode, true));
    18.                         me.HandleResult(NME.onKeyChange(keyCode, false));
    19.                     }
    20.                 }
    21.             }
    22.         });
    23.         return true;
    24.     }
    复制代码






    本文来自:http://www.cnblogs.com/pelephone/p/haxe_record.html
    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    
    关闭

    站长推荐上一条 /4 下一条

    QQ|手机版|Archiver|网站地图|小黑屋|守望者 ( 京ICP备14061876号

    GMT+8, 2019-10-23 20:42 , Processed in 0.050081 second(s), 37 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

    快速回复 返回顶部 返回列表