46

如果您是根据标题提出这个问题但对蒙古语不感兴趣,您可能正在寻找此问答:


我一直在学习 Swift,以便为传统的蒙古语开发 iOS 应用程序。问题是传统的蒙古文是从上到下,从左到右垂直书写的。我的问题是如何垂直显示文本并且仍然有换行工作?

如果你陪我一会儿,我会试着更清楚地解释这个问题。下面是我想要实现的那种文本视图的图像。万一外国脚本让你失望,我已经包含了遵循相同模式的英文文本。事实上,如果应用程序有任何英文文本要显示,它应该是这样的。

在此处输入图像描述

对于简单的单行 UILabel,顺时针旋转 90 度即可。但是,对于多行 UITextView 我需要处理换行。如果我只是简单地旋转 90 度,那么写的第一件事最终会在最后一行。

到目前为止,我已经制定了一个我认为可以克服这个问题的计划:

  1. 制作一个自定义字体,其中所有字母都垂直镜像。
  2. 将文本视图顺时针旋转 90 度。
  3. 水平镜像文本视图。

在此处输入图像描述

那应该照顾文本换行。

我可以做镜像字体。但是,我不知道如何为 UITextView 的旋转和镜像进行 Swift 编码。我发现以下链接似乎为解决方案的某些部分提供了提示,但它们都在 Objective C 中,而不是在 Swift 中。

应用商店里有传统的蒙古语应用(比如thisthis),但我还没有找到任何人分享他们的源代码,所以我不知道他们在幕后做了什么来显示文本。我计划将我的代码开源,这样其他人将来为数百万阅读传统蒙古语的人开发应用程序就不那么困难了。您能为这项工作提供的任何帮助将不胜感激,不仅是我,还有蒙古人民。即使您不了解自己,对这个问题进行投票以使其更加明显也会有所帮助。

更新

@sangonz 的答案仍然是一个很好的答案,但我暂时将其取消标记为已接受的答案,因为我无法让一切正常工作。具体来说:

  • 启用滚动(通过将自定义视图嵌入到滚动视图中或通过子类化 UIScrollView)。在 github 项目中,@sangonz 说这应该很容易,但它不适合我。
  • 在方向改变时重新布局(而不是拉伸)字线。我认为通过更多的研究来解决这个问题应该不会太难。
  • 为什么文本行不一直到视图的边缘?底部有一个很大的空隙。
  • 如何解除自定义垂直视图的 NSTextStorage 与其他 UITextView 的链接。(见这个问题

到目前为止,我一直在使用我上面提出的原始方法,但我真正想要的是得到类似@sangonz 提议的东西。

我现在也在考虑替代方法,例如

4

2 回答 2

21

Edit: This is how I finally did it.

Here's a very basic implementation in my GitHub: Vertical-Text-iOS.

Nothing fancy, but it works. Finally I had to mix TextKit and image processing. Take a look at the code. It involves:

  1. Subclassing NSTextContainer to get the right text dimensions.
  2. Creating a custom UIView to render the text applying affine transformations to each line and rendering using NSLayoutManager to keep all TextKit features.

TextKit way

The proper way to keep all native text benefits (e.g. highlighting, selection...) is to use standard TextKit APIs. The method you are proposing would break all that or would possibly result in strange behaviour.

However, looks like TextKit in iOS does not support vertical orientation out-of-the-box yet, but it is prepared for that. As a side note, in OS X it is somewhat supported and you could call textView.setLayoutOrientation(.Vertical), but it still has some limitations.

The NSTextLayoutOrientationProvider protocol defines an interface providing the default orientation for text laid out in a conforming object, in absence of an explicit NSVerticalGlyphFormAttributeName attribute. The only UIKit class that implements this interface is NSTextContainer, whose default implementation returns NSTextLayoutOrientationHorizontal. An NSTextContainer subclass that handles vertical text could set this property to NSTextLayoutOrientationVertical to support the custom layout orientation logic.

Source: UIKit > NSTextLayoutOrientationProvider Protocol Reference for iOS

In conclusion, you should start subclassing NSTextContainer, and you will have to deal with NSLayoutManager and NSTextContainer a lot.


Custom image processing way

If, on the other hand you decide to follow your custom text rendering I suggest the following approach.

  1. Render the normal text to a hidden layer with a normal font. Give it the correct size to its bounding box.
  2. Get the text properties, mainly text height and line spacing.
  3. Process the image drawing each line in reverse order from bottom to top as you can see in the image below. You should get a new CGImage as a result.
  4. Rotate the image creating a UIImage and setting the correct UIImageOrientation value.
  5. Insert that image into a UIScrollView that only allows horizontal scrolling.

Beware this method renders the whole text, so don't use it for very long texts. If you need to do that, you will need to consider a tiling approach. Watch WWDC 2013 > 217 - Exploring Scroll Views on iOS 7.

this image

Good luck!

Update: (image from github project)

enter image description here

于 2015-02-24T11:43:56.993 回答
4

如果您要旋转文本,我建议您使用从右到左的布局,这样您就可以跳过镜像步骤(并且只是旋转另一种方式)。

您应该能够只设置标签/文本视图的transform属性:

view.transform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(CGFloat(-M_PI_2)), view.bounds.width, view.bounds.height)

旋转后需要平移,因为视图围绕其原点旋转(在左上角)。

好消息是手势和点击会在像素发生变化的同时发生变化,因此控件会继续按照您期望的方式工作。

于 2015-02-24T12:53:46.320 回答