问题描述
如果您是根据标题来到这个问题的,但对蒙古语不感兴趣,那么您可能会在寻找以下问答:
If you came to this question based on the title but are not interested in Mongolian, you might be looking for this Q&A instead:
我一直在学习Swift,以便为传统的蒙古语开发iOS应用.问题在于传统的蒙古语是从上到下,从左到右垂直书写的.我的问题是如何垂直显示文本并且仍然有换行功能?
I've been learning Swift in order to develop iOS apps for traditional Mongolian. The problem is that traditional Mongolian is written vertically from top to bottom and from left to right. My question is how do I display text vertically and still have line wrapping work?
如果您和我呆一分钟,我将尝试更清楚地解释问题.下面是我想要实现的那种文本视图的图像.如果外来脚本使您失望,我会提供遵循相同模式的英文文本.实际上,如果该应用程序要显示任何英文文本,则它应该是这样.
If you stay with me for a minute, I'll try to explain the problem more clearly. Below is an image of the kind of text view I would like to achieve. In case the foreign script throws you off, I have included English text that follows the same pattern. In fact, if the app has any English text to display, this is how it should look.
对于简单的单行UILabel,可以顺时针旋转90度.但是,对于多行UITextView,我需要处理换行.如果我只是旋转90度,那么写的第一件事将最终出现在最后一行.
For a simple one-line UILabel, a 90 degree clockwise rotation would work. However, for a multi-line UITextView I need to deal with line wrapping. If I just do a plain 90 degree rotation, the first thing written will end up being on the last line.
到目前为止,我已经制定了一个计划,我认为可以克服这个问题:
So far I have made a plan that I think can overcome this problem:
- 制作一种自定义字体,其中所有字母均垂直镜像.
- 将文本视图顺时针旋转90度.
- 水平镜像文本视图.
那应该注意文字换行.
That should take care of the text wrap.
我可以做镜像字体.但是,我不知道如何对UITextView的旋转和镜像进行Swift编码.我发现以下链接似乎可以提示解决方案的各个部分,但它们全都在Objective C中,而不在Swift中.
I can do the mirrored font. However, I don't know how to do the Swift coding for the rotation and mirroring of the UITextView. I've found the following links that seem to give hints to parts of the solution, but they are all in Objective C and not in Swift.
- How to rotate sub-views around their own centres?
- Rotate UIView around its center keeping its size
- iOS: Mirror content on screen
- Mirroring UIView
应用程序商店中有传统的蒙古语应用程序(例如此和此),但我没有找到尚未共享其源代码的任何人,因此我不知道他们在幕后显示文本的方式.我计划将我的代码开源,以便将来其他人不必为数百万阅读传统蒙古语的人开发应用程序.您能为这项工作提供的任何帮助将不胜感激,不仅是我本人,还有蒙古人民.即使您不认识自己,也可以提出这个问题以使其更显眼.
There are traditional Mongolian apps in the app store (like this and this) but I haven't found anyone yet who is sharing their source code, so I don't know what they are doing behind the scenes to display the text. I plan to make my code open source so that it is not so hard for others in the future to develop apps for the several million people who read traditional Mongolian. Any assistance you can give to this endeavor would be much appreciated, not just by me but also by the Mongolian people. Even if you don't know yourself, upvoting this question to make it more visible would help.
@sangonz的答案仍然是一个不错的答案,但我暂时未将其标记为可接受的答案,因为我无法使所有工作正常进行.具体来说:
@sangonz's answer is still a great answer, but I temporarily unmarked it as the accepted answer because I just couldn't get everything to work. Specifically:
- 启用滚动(通过将自定义视图嵌入滚动视图或通过).在github项目中,@ sangonz说这应该很容易,但这对我来说不是.
- 获取方向改变时字线的中继(而不是拉伸).我认为通过更多的研究可以解决这个问题.
- 为什么文本行不会一直延伸到视图的边缘?底部有很大的差距.
- (请参阅)
- Enabling scrolling (either by embeding the custom view in a scrollview or by subclassing UIScrollView). In the github project, @sangonz said this should be easy, but it wasn't for me.
- Getting a relayout (rather than stretching) of the word lines on an orientation change. I think this shouldn't be too hard to solve with a little more research.
- Why don't the text lines go all the way to the edge of the view? There is a big gap at the bottom.
- (see this question)
到目前为止,我一直在使用我上面提出的原始方法,但是我真正想要的是得到类似于@sangonz建议的工作方式.
Up to this point I have been using the original method I proposed above, but what I really want is to get something like what @sangonz proposed working.
我现在也在考虑其他替代方法,例如
I am also now considering alternate methods like
- 使用核心文字,缺点:感觉就像在重新发明轮子一样
- ,缺点:Apple不再将WebKit用于其
UITextView
- Using Core Text, Disadvantage: it feels like reinventing the wheel
- Using WebKit, Disadvantage: Apple no longer uses WebKit for their
UITextView
推荐答案
这就是我最终做到的方式.
This is how I finally did it.
这是我的GitHub中非常基本的实现: Vertical-Text-iOS .
Here's a very basic implementation in my GitHub: Vertical-Text-iOS.
没什么花哨的,但是有效.最后,我不得不混合使用TextKit和图像处理.看一下代码.它涉及:
Nothing fancy, but it works. Finally I had to mix TextKit and image processing. Take a look at the code. It involves:
- 子类化
NSTextContainer
以获得正确的文本尺寸. - 创建自定义
UIView
以对每行应用仿射变换来呈现文本,并使用NSLayoutManager
进行呈现以保留所有TextKit功能.
- Subclassing
NSTextContainer
to get the right text dimensions. - Creating a custom
UIView
to render the text applying affine transformations to each line and rendering usingNSLayoutManager
to keep all TextKit features.
TextKit方式
保留所有本机文本优点(例如,突出显示,选择...)的正确方法是使用标准TextKit API.您提出的方法会破坏所有这些方法,或者可能导致奇怪的行为.
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.
但是,看起来iOS中的TextKit尚不支持现成的垂直方向,但是已经为此做好了准备.附带说明一下,在OS X中它得到了某种支持,您可以调用textView.setLayoutOrientation(.Vertical)
,但是它仍然有一些限制.
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.
来源: UIKit> NSTextLayoutOrientationProvider
iOS协议参考
Source: UIKit > NSTextLayoutOrientationProvider
Protocol Reference for iOS
最后,您应该开始子类化NSTextContainer
,并且您将不得不处理NSLayoutManager
和NSTextContainer
很多事情.
In conclusion, you should start subclassing NSTextContainer
, and you will have to deal with NSLayoutManager
and NSTextContainer
a lot.
另一方面,如果您决定遵循自定义文本呈现方式,则建议采用以下方法.
If, on the other hand you decide to follow your custom text rendering I suggest the following approach.
- 将常规文本呈现到具有常规字体的隐藏层.为其边框设置正确的大小.
- 获取文本属性,主要是文本高度和行距.
- 处理图像,如下图所示,从下到上以相反的顺序绘制每条线.结果,您应该得到一个新的
CGImage
. - 旋转图像,创建一个
UIImage
并设置正确的UIImageOrientation
值. - 将该图像插入到仅允许水平滚动的
UIScrollView
中.
- Render the normal text to a hidden layer with a normal font. Give it the correct size to its bounding box.
- Get the text properties, mainly text height and line spacing.
- 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. - Rotate the image creating a
UIImage
and setting the correctUIImageOrientation
value. - Insert that image into a
UIScrollView
that only allows horizontal scrolling.
请注意,此方法将呈现整个文本,因此请勿将其用于很长的文本.如果需要这样做,则需要考虑平铺方法.观看 WWDC 2013> 217-在iOS 7上浏览滚动视图.
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.
祝你好运!
更新:(来自github项目的图片)
这篇关于如何在Swift中为iOS制作垂直文本UILabel和UITextView?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!