图8-25演示了Core Text中的一个基本问题。 这涉及将Core Text绘制到列中。当您布置列时,文本应该在每列的边缘换行,而不是在它们之间继续。例如,在右列的顶部,单词sitting应该出现在第一列的第二行,因为它原本是在tired of之后的。相反,它放置在右侧绘图第二列的顶部。文本穿过列,然后在下一列绘制,而不是在第一列一直向下绘制,然后在下一列再向下绘制。
图8-25文本本身并不知道在这个复杂的路径中在哪里换行。在开始下一行之前,文本将跨两列进行流动(绘制)而不是分别在每一列向下移动。
问题是Core Text框架列表将整个Bezier路径视为一个单一的形状(您在图8-26中看到的路径)。它的两个竖直矩形意味着显示独立的文本列。 然而,发生的情况是,Core Text framesetter只使用一个测试来构建其框架。它确定(只考虑)路径内的点和路径外的点。所有其他注意事项都省略。Core Text和iOS通常没有“列”的概念,所以默认的技术不支持我们所期望的逐列布局。
图8-26该路径包含两个矩形。
图8-27显示了我想要的布局。在这里,sitting在tired of之后进行了合适的换行。 文本在第一列向下排列,然后继续到第二列再向下排列。此布局将两列视为单个的输出流。 文本从一列移动到另一列。
图8-27本文以合适的方式遵从列布局来排列。
比较图8-25和8-27中的视觉风格。图8-27看起来是正确的“文本”布局,一系列格式良好的短段落。图8-25右列显示了更多的间隙线和较少的文本。其布局看起来略逊于图8-27中的布局。
我通过调用清单8-1中的DrawAttributedStringInBezierPath()
生成了图8-25的“before”映像。从图8-25中的错误布局流到图8-27中的正确布局,它实际上只需要很少的工作来实现此功能。清单8-2显示了是实现的。
这个新函数叫做DrawAttributedStringIntoSubpath()
。 它以一个一个的子路径为基础,并使用无法绘制到路径中的属性字符串内容更新字符串余数参数。要完成此操作,它会查询Core Text框架的可见字符串范围。此函数计算属性字符串的余数,即不可见部分,并将其分配给余数参数。
清单8-2中的第二个函数是DrawAttributedStringInBezierSubpaths()
。此入口点遍历路径的子路径。在每个阶段,它检索“其余”字符串并将其应用到下一个绘图阶段。该函数在完成绘制子路径或其余字符串长度减少到零时返回。
清单8-2将属性字符串绘制到独立子路径中
1 | void DrawAttributedStringIntoSubpath( |
Image Cutouts
清单8-2最适用于绘图上下文中的列或其他独立元素。对于使用偶数/奇数填充规则创建的孔的布局不适用。如果您使用DrawAttributedStringInBezierSubpaths()
函数,您将最终在整个路径上绘制文本,然后再次进入该孔,因为外部路径及其内部孔将分为两个不同的子路径。
要处理利用偶数/奇数填充规则的复杂路径,请以让局部(路径)有意义的方式执行自己的路径分解。然后直接调用DrawAttributedStringIntoSubpath()
函数。
也就是说,偶数/奇数填充规则使您能够在路径中创建简单的Cutouts。这些可以应用图像绘制,如图8-28所示。为了绘制这个,我创建了一个内部矩形,并将其添加到我的路径。 这建立了一个足够大的“洞”来绘制我的图像。
图8-28将图像绘制到路径切口(cutout)上。
本文翻译自《iOS Drawing Practical UIKit Solutions》作者:Erica Sadun,翻译:Cheng Dong。如果觉得本书不错请购买支持正版:亚马逊购买传送门,本书所有源代码可在GitHub上下载。译者虽然力求做到信,达,雅,但是由于时间仓促加之译者水平十分有限,文中难免会出现不正确,不准确,词不达意,难于理解的地方,还望各位批评指正,共同进步,谢谢。转载请注明出处。