Как сделать вертикальный текст UILabel и UITextView для iOS в Swift?
Если вы пришли к этому вопросу на основе названия, но не заинтересованы в монгольском, вы можете искать этот Q & A вместо:
Я изучаю Swift для разработки приложений iOS для традиционного монгольского. Проблема в том, что традиционный монгольский язык написан вертикально сверху донизу и слева направо. Мой вопрос заключается в том, как отображать текст по вертикали и все еще работать с оберткой строк?
Если вы останетесь со мной на минутку, я постараюсь объяснить проблему более четко. Ниже приведен образ такого текстового представления, которого я хотел бы достичь. Если иностранный script отбрасывает вас, я включил текст на английском языке, который следует по той же схеме. На самом деле, если приложение имеет какой-либо текст на английском языке, вот как он должен выглядеть.
![enter image description here]()
Для простой однолинейной UILabel будет работать поворот на 90 градусов по часовой стрелке. Однако для многострочного UITextView мне нужно иметь дело с оберткой строк. Если я просто сделаю обычный поворот на 90 градусов, первое, что написано, окажется на последней строке.
До сих пор я сделал план, который, как я думаю, может решить эту проблему:
- Создайте собственный шрифт, в котором все буквы зеркалируются вертикально.
- Поворот текстового вида на 90 градусов по часовой стрелке.
- Зеркальное отображение текста по горизонтали.
![enter image description here]()
Это должно позаботиться об обертке текста.
Я могу сделать зеркальный шрифт. Тем не менее, я не знаю, как сделать Swift кодирование для вращения и зеркалирования UITextView. Я нашел следующие ссылки, которые, похоже, дают подсказки частям решения, но все они находятся в Objective C, а не в Swift.
В магазине приложений есть традиционные монгольские приложения (например, this и это), но я еще не нашел никого, кто делится своим исходным кодом, поэтому я не знаю, что они делают за кулисами, чтобы отобразить текст. Я планирую сделать свой код открытым исходным кодом, чтобы другим в будущем не было разработано приложений для нескольких миллионов человек, которые читали традиционный монгольский язык. Любая помощь, которую вы можете оказать этому начинанию, будет высоко оценена не только мной, но и монгольским народом. Даже если вы не знаете себя, это поможет повысить этот вопрос, чтобы сделать его более заметным.
Update
Ответ на
@sangonz по-прежнему остается отличным ответом, но я временно не обозначил его как принятый ответ, потому что я просто не мог заставить все работать. В частности:
- Включение прокрутки (путем встраивания пользовательского представления в scrollview или под подклассом UIScrollView). В проекте github @sangonz сказал, что это должно быть легко, но это было не для меня.
- Получение ретрансляции (а не растяжения) строк слова при изменении ориентации. Я думаю, что это не должно быть слишком сложно решить с небольшим количеством исследований.
- Почему текстовые строки не пересекаются до края представления? В нижней части есть большая щель.
-
Как отключить NSTextStorage пользовательского вертикального представления от другого UITextView. (см. этот вопрос)
До этого момента Я использовал оригинальный метод, предложенный выше, но я действительно хочу получить что-то вроде того, что предложил @sangonz.
Я также рассматриваю альтернативные методы, такие как
Ответы
Ответ 1
Изменить: Вот как я это сделал.
Вот очень простая реализация в моем GitHub: Vertical-Text-iOS.
Ничего особенного, но это работает. Наконец, мне пришлось смешивать TextKit и обработку изображений. Взгляните на код. Он включает в себя:
- Подкласс
NSTextContainer
, чтобы получить правильные размеры текста.
- Создание пользовательского
UIView
для визуализации текста, применяющего аффинные преобразования к каждой строке, и рендеринг с использованием NSLayoutManager
для сохранения всех функций TextKit.
Способ TextKit
Правильный способ сохранить все преимущества родного текста (например, выделение, выделение...) - использовать стандартные API TextKit. Метод, который вы предлагаете, нарушит все это или может привести к странному поведению.
Однако, похоже, что TextKit в iOS еще не поддерживает вертикальную ориентацию, но он готов к этому. Как примечание, в OS X оно несколько поддерживается, и вы можете вызвать textView.setLayoutOrientation(.Vertical)
, но он все еще имеет некоторые ограничения.
Протокол NSTextLayoutOrientationProvider
определяет интерфейс обеспечивая ориентацию по умолчанию для текста, изложенного в соответствующем объект, в отсутствие явного NSVerticalGlyphFormAttributeName
атрибут. Единственным классом UIKit, который реализует этот интерфейс, является NSTextContainer
, реализация по умолчанию которого возвращается NSTextLayoutOrientationHorizontal
. Подкласс NSTextContainer
, который дескриптор вертикального текста может установить это свойство в NSTextLayoutOrientationVertical
для поддержки пользовательского макета логика ориентации.
Источник: UIKit > NSTextLayoutOrientationProvider
Ссылка на протокол для iOS
В заключение вы должны начать подклассификацию NSTextContainer
, и вам придется иметь дело с NSLayoutManager
и NSTextContainer
много.
Способ обработки пользовательских изображений
Если, с другой стороны, вы решили следовать своему пользовательскому текстовому рендерингу, я предлагаю следующий подход.
- Отредактируйте обычный текст на скрытый слой с обычным шрифтом. Дайте ему правильный размер для своей ограничивающей рамки.
- Получить свойства текста, главным образом, высоту текста и межстрочный интервал.
- Обработать изображение, рисуя каждую строку в обратном порядке снизу вверх, как вы можете видеть на изображении ниже. В результате вы должны получить новый
CGImage
.
- Поверните изображение, создав
UIImage
и установите правильное значение UIImageOrientation
.
- Вставить это изображение в
UIScrollView
, которое разрешает только горизонтальную прокрутку.
Остерегайтесь, что этот метод отображает весь текст, поэтому не используйте его для очень длинных текстов. Если вам нужно это сделать, вам нужно будет рассмотреть подход к черепице. Смотреть WWDC 2013 > 217 - Изучение прокрутки на iOS 7.
![this image]()
Удачи!
Обновление: (изображение из проекта github)
![enter image description here]()
Ответ 2
Если вы собираетесь повернуть текст, я бы предложил использовать макет справа налево, чтобы вы могли пропустить шаг зеркалирования (и просто повернуть в другую сторону).
Вы должны просто установить свойство label/textview transform
:
view.transform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(CGFloat(-M_PI_2)), view.bounds.width, view.bounds.height)
Вам нужно перевести после поворота, потому что представление вращается вокруг его начала (в верхнем левом углу).
Хорошей новостью является то, что жесты и краны преобразуются одновременно с пикселями, поэтому элементы управления продолжают работать так, как вы ожидаете.