如何在Swift中为iOS创build垂直文本UILabel和UITextView?
如果你根据标题来到这个问题上,但是对蒙古人不感兴趣,你可能会在寻找这个问答:
- Swift:如何为UIButton和UILabel旋转文本?
我一直在学习Swift,以便为传统的蒙古语开发iOS应用程序。 问题是传统的蒙古文是从上到下,从左到右的垂直书写。 我的问题是如何垂直显示文本,仍然有线包装工作?
如果你留在我身边一会儿,我会试着更清楚地解释这个问题。 下面是我想要实现的那种文本视图的图像。 如果外文脚本丢掉了,我已经包含了遵循相同模式的英文文本。 事实上,如果应用程序有任何英文文本显示,这是它应该看起来。
对于一个简单的单线UILabel,90度顺时针旋转将起作用。 但是,对于多行UITextView,我需要处理换行。 如果我只是做一个简单的90度旋转,写的第一件事就会落在最后一行。
到目前为止,我已经制定了一个计划来解决这个问题:
- 制作所有字母垂直镜像的自定义字体。
- 顺时针旋转文本视图90度。
- 水平镜像文本视图。
这应该照顾文本换行。
我可以做镜像字体。 但是,我不知道如何做UITextView的旋转和镜像的Swift编码。 我发现下面的链接似乎给解决scheme的一部分提示,但是它们都在Objective C中,而不是在Swift中。
- 如何旋转他们自己的中心周围的子视图?
- 围绕其中心旋转UIView保持其大小
- iOS:在屏幕上镜像内容
- 镜像UIView
在app store里有传统的蒙古应用程序(比如这个和这个 ),但是我还没有find任何人分享他们的源代码,所以我不知道他们在幕后做了什么来显示文本。 我打算让自己的代码是开源的,这样对于其他人来说,为了阅读传统蒙古语的数百万人开发应用程序并不难。 任何援助,你可以给这个努力,将不胜感激,不仅由我,而且蒙古人民。 即使你不了解自己,提出这个问题,使其更明显将有所帮助。
更新
@ sangonz的答案仍然是一个很好的答案,但是我暂时没有把它作为被接受的答案,因为我不能让所有的东西都起作用。 特别:
- 启用滚动(通过在滚动视图中embedded自定义视图或通过inheritanceUIScrollView )。 在github项目中,@sangonz说这应该很容易,但这不适合我。
- 根据方向更改获得重新布局(而不是拉伸)字线。 我觉得这应该不是太难以解决多一点研究。
- 为什么文本行不能一直走到视图的边缘呢? 底部有一个很大的差距。
-
如何从另一个UITextView中断开自定义垂直视图的NSTextStorage。(看这个问题 )
到目前为止, 我一直在使用我上面提出的原始方法 ,但是我真正想要的是像@sangonz提出的那样工作。
我现在也在考虑类似的替代方法
- 使用核心文本 ,缺点:感觉就像重新发明轮子
- 使用WebKit ,缺点:Apple不再为他们的
UITextView
使用WebKit
编辑:这是我终于做到了。
这是我的GitHub: Vertical-Text-iOS中的一个非常基本的实现。
没有什么幻想,但它的作品。 最后,我不得不混合TextKit和image processing。 看看代码。 它涉及:
-
NSTextContainer
以获得正确的文本维度。 - 创build一个自定义的
UIView
来渲染文本应用仿射变换到每一行和使用NSLayoutManager
呈现保持所有的TextKitfunction。
TextKit的方式
保持所有本地文本优点(例如突出显示,select…)的正确方法是使用标准的TextKit API。 你提出的方法会打破所有这些或可能导致奇怪的行为。
但是,iOS中的TextKit看起来并不支持垂直方向的开箱即用,但它已经做好了准备。 作为一个侧面说明,在OS X中它有点支持,你可以调用textView.setLayoutOrientation(.Vertical)
,但是它仍然有一些限制。
NSTextLayoutOrientationProvider
协议定义了一个接口,该接口为没有显式NSVerticalGlyphFormAttributeName
属性的符合对象中的文本提供默认方向。 唯一实现此接口的UIKit类是NSTextContainer
,其默认实现返回NSTextLayoutOrientationHorizontal
。 处理垂直文本的NSTextContainer
子类可以将此属性设置为NSTextLayoutOrientationVertical
以支持自定义布局方向逻辑。
来源: UIKit> NSTextLayoutOrientationProvider
于iOS的NSTextLayoutOrientationProvider
协议参考
总之 ,你应该开始NSTextContainer
,你将不得不处理NSLayoutManager
和NSTextContainer
。
自定义image processing方式
另一方面,如果您决定遵循您的自定义文本呈现,我build议采用以下方法。
- 使用普通字体将正常文本渲染到隐藏层。 给它的边界框正确的大小。
- 获取文本属性 ,主要是文本高度和行距。
- 如下图所示,按照从下到上的顺序逐行处理图像。 结果你应该得到一个新的
CGImage
。 - 旋转图像创build一个
UIImage
并设置正确的UIImageOrientation
值。 - 将该图像插入仅允许水平滚动的
UIScrollView
。
要小心这个方法呈现整个文本,所以不要用它很长的文本。 如果你需要这样做,你将需要考虑平铺的方法。 观看WWDC 2013> 217 – 探索iOS 7上的滚动视图 。
祝你好运!
更新:(从github项目的图像)
如果你要旋转文本,我会build议使用从右到左的布局,以便你可以跳过镜像步骤(只是旋转另一种方式)。
你应该能够设置标签/ textview的transform
属性:
view.transform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(CGFloat(-M_PI_2)), view.bounds.width, view.bounds.height)
旋转后需要翻译,因为视图围绕其原点(在左上angular)旋转。
好消息是手势和水龙头在像素的同时被转换,所以控件继续以你期望的方式工作。