textarea对于中文结尾(断行处刚好是中文)无法正常断行,要解决这个问题,必须了解textarea是如何断行的,实际上查看其代码知道,展示时是通过splitWords函数把文字全部解析为单词,每个单词作为一个text对象添加到frame中,由于单词按照空格间隔,所以无法断中文的"单词".原来TextArea的源码中分词函数如下:
private void splitWords(String fullText, int style) { int beginIndex = 0; int endIndex = 0; String word; do { endIndex = fullText.indexOf(' ', beginIndex); if (endIndex == -1) { word = fullText.substring(beginIndex); } else { word = fullText.substring(beginIndex, endIndex); } if (word.length() != 0) { Text textWidget = new Text(); textWidget.setText(word); if (style != Font.STYLE_PLAIN) { textWidget.setDefaultFontStyle(style); } add(textWidget); } beginIndex = endIndex + 1; } while (endIndex != -1); }
Kuix的论坛上提供了下面的替换函数解决中文断行的问题.
private void splitWords(String fullText, int style) { String str = fullText;//+" "; String word=""; int len = str.length()-1; for (int i = 0; i <= len; i++) { char ch = str.charAt(i); if(i!=len) word = word + ch; if ((ch >= 48 && ch <= 57) || (ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122)) continue; if (word.length() != 0 || i==len) { Text textWidget = new Text(); textWidget.setText(word); if (style != Font.STYLE_PLAIN) { textWidget.setDefaultFontStyle(style); } add(textWidget); word = ""; } } }
应该说是做的很差的函数,对于数字,大小写26个英文子母外的其他字符都作为word的分隔符,这是相当有问题的,实际上应该把中文区间和空格作为分隔的基础,这个方法本身还有一个更大的缺陷,注意到原文的英文式分词是不把空格加进去的,也就是说Kuix默认会把每个text控件用一个空格的间隔分隔开了,所以替换为上述函数的结果就是显示中文虽然可以正常换行,但是每个中文之间都会有一个空格间隔着,看起来不美观,而且也很浪费空间.
那么这个"隐藏"的空格是哪里来的,查TextArea的源代码,发现getGap的函数很有意思,不是继承Widget从样式中获取,而是直接获得空格的宽度,所以实际上TextArea容器中每个widget的间隔就是一个空格,修改getGap函数可以去掉空格:
/* (non-Javadoc) * @see org.kalmeo.kuix.widget.Widget#getGap() */ public Gap getGap() { if (cachedGap == null) { // cachedGap = new Gap(getFont().charWidth(' '), 0); cachedGap = new Gap(0, 0); } return cachedGap; }
这样可以去掉中文之间的间隔,但是如果你试着去读取6,7页中文数据的话,立马就会报告Out of memory的错误,每个中文创建一个Text显然是相当浪费的,更完美的解决方案当然是自己断行.这里顺便说一下Kuix的标签和分行机制,首先看一下我的一个测试断行的分析描述:
1 无标签时支持<break/> 2 textarea不支持<break/>,不继承上一级容器的align属性,默认align是top,有中文时断行错误,出现只有很少文字的一行. 3 对英文断行也有缺陷,如果第一个单词就过长,会超出界限 4 多个空格也认为是1个空格,不支持回车,\n,<br>会保错 5 有意思的属性styled,default false,用途 Define if the text area use pseudo html style syntax. The value is a boolean (true or false). 假冒html样式?似乎是采用html的样式?整个reflow()函数都在为这个属性服务
测试结果发现textarea似乎支持有限的html标签,实际上支持的html标签包括 img,i,b,strong,u,br,p,div等,也就是说对html标签的支持只包含字体,段落回车和图片。但是如果直接写在标签中都必须做转义才能使用,否则会报Unknow tag的错误,比如<br/>必须转义为<;br/>;还有另外一种形式可以不用转义,此时可以直接写入html标签和<break/>,如下:
<textarea style="align:top-left"><![CDATA[test<br>new line]]></textarea>
这个是题外话,需要进一步了解请自行看TextArea.reflow和LightXmlParser的代码,注意到reflow大多数的代码其实都是解析和实现简单的html标签。
Kuix断行实际上是依靠text来实现的,textarea只不过保证英文单词不被拆分在不同的行,而且猜测默认都是采用flowlayout来实行布局。要实现软回车,必须自己加上Kuix的标准标签<break></break>.而这个标签上面说过,在textarea的内容中也是不支持的.那么要实现中文断行,而且效果较好的话,就只能自己根据屏幕大小和字体断行,另外TextArea还有一个问题就是本身不支持textfield的编辑功能,这也是一个相当大的缺陷,作者说是因为两者展示时采用的方法不同,要实现它的编辑功能,必须另外弹出一个窗口进行编辑,具体方法不再提供,这里只分析Kuix的断行的处理方式,大家可以从网上另外找寻中文断行的代码参考.