代码改变世界

Android排版和POI

2012-12-01 03:53 onm 阅读(...) 评论(...) 编辑 收藏

排版是个相对复杂的东西,光就字体排版而论就涉及到很多东西,http://zh.wikipedia.org/wiki/%E5%AD%97%E4%BD%93,这里有一些相关的资料。最近研究了一下Office系列格式的排版问题。字体排版是很麻烦的一个东西,幸好Android上提供了一些有用的工具类。

先看一下Android提供的相关的包,android.graphics包下提供了图形方面的工具,其中也有一些和字体有关的类,比如Paint可以设置字号等,Paint.FontMetrics提供了一些字体测量的工具,FontMetrics的一些信息可以参考:http://blog.csdn.net/a_large_swan/article/details/7339902。Paint还提供了breakText()等相关的方法对字进行测量和折行操作。但是Paint提供的方法无法对复杂的带有属性的文字段进行正确的测量,所谓带有属性的文字段,就是某个区间的文字有一些加粗,斜体,字号,对齐,图文混合,下标、上标等等进行测量。

在android.text包中提供了上述的功能类,且这个包和子包下面提供了非常丰富的富媒体排版设置。重要的就是Span概念,有些相关的类和接口定义了前面所说的带有属相的文本,通过设定Span的一些具体实现来标示属性。然后在绘制的时候Android的绘图类会自动绘制相应的属性。http://my.oschina.net/u/251121/blog/75078,这篇文章示例了大部分使用案例。总的来说Span总共分为两类,CharacterStyle和ParagraphSytle。字符的样式和段落的样式。

android.text.Layout子类提供了排版的功能,它会考虑带属性的字符串,也就是设有Span的字符串,然后进行排版布局。该类还提供了绘制方法,参考:http://blog.sina.com.cn/s/blog_643e8386010150eg.html。通过查看实现的源码可以看到,Layout的绘制功能获取了所有Span的信息,后然进行measure和layout。并且可以通过这个类获取布局后的属性,比如高度,宽度,每行的信息等。

解析和渲染Office格式的Java实现有个POI,项目比较老,却也不是很成熟。移植到Android平台上比较困难。难在三方面,一方面是POI使用了Java2D的Graphics系统,Android与之基本完全不兼容,awt包在Android基本没有,也没有成熟的port。另一方面是内存占用,手机上对于内存占用很敏感,POI的一些做法对于这种场景问题很多。最后是一些第三方的包在Android上不支持。

首先第一方面可以在Android上找到一些相应类似的类进行替换,但是接口形式和功能有差别,需要做较多改动。对于文字排版参考前面Android排版的极少,Java2D中用到的一些字体排版处理的类Android上可以找到一些对应。比如Android上的Span,Java2D里对应AttributeString,Android上的Layout对应Java2D里面的一些类,有TextMeasure,TextLine等一些。对于awt的geom包,google code上有个port。http://code.google.com/p/awt-android-compat/。geom包是可用的,其它基本不能使用。

第二方面,主要在于图片内存占用的优化,POI默认图片全部加载到了内存中,改为绘制时加载,绘制完销毁的策略。使用NPOI相关类,减少内存占用。对于pptx项目由于用到了xmlbeans,每个元素都继承自xmbeans提供的一个基类,且所有slide的信息完全加载到内存,每个xmbeans的基类大概是88bytes内存的占用量,但是数量惊人,当slide中元素比较多的时候,内存占用非常的多。优化考虑点是绘制时再加载slide元素信息,这点还没有实现。

第三方面,pptx项目用到了java开头一些包,android没有提供,并且打包成dex包的时候,对于java开头的包不支持,停止生成。davlik的wiki上有个文档,http://code.google.com/p/dalvik/wiki/JavaxPackages,叫做repacakge,就是打包的时候将包名重命名。

移植POI-HSLF(ppt) 和POI-XLSF(pptx)对应的工作还有很多。移植代码放在github上了。

https://github.com/qhm123/POI-Android