Как сделать вертикальный текст UILabel и UITextView для iOS в Swift?
Если вы пришли к этому вопросу, основываясь на названии, но не интересуетесь монгольским языком, вы можете вместо этого искать вопросы и ответы:
Я изучал Swift, чтобы разрабатывать приложения для iOS для традиционного монгольского языка. Проблема в том, что традиционный монгольский написан вертикально сверху вниз и слева направо. У меня вопрос, как я могу отображать текст по вертикали и при этом работать с переносом строк?
Если вы останетесь со мной на минуту, я постараюсь объяснить проблему более четко. Ниже приведено изображение вида текста, который я хотел бы получить. На случай, если иностранный скрипт вас отбросит, я включил текст на английском языке, который следует той же схеме. На самом деле, если приложение отображает текст на английском языке, это должно выглядеть так.
Для простой однострочной UILabel будет работать поворот на 90 градусов по часовой стрелке. Однако для многострочного UITextView мне нужно иметь дело с переносом строк. Если я просто сделаю простой поворот на 90 градусов, первое, что написано, окажется в последней строке.
Пока что я составил план, который, я думаю, может решить эту проблему:
- Создайте собственный шрифт, в котором все буквы будут отображаться вертикально.
- Поверните текстовое представление на 90 градусов по часовой стрелке.
- Зеркально отразите текстовый вид по горизонтали.
Это должно заботиться о переносе текста.
Я могу сделать зеркальный шрифт. Однако я не знаю, как выполнить кодирование Swift для поворота и зеркального отображения UITextView. Я нашел следующие ссылки, которые, кажется, дают подсказки частям решения, но все они в Objective C, а не в Swift.
- Как вращать подвиды вокруг своих центров?
- Поверните UIView вокруг его центра, сохраняя его размер
- iOS: зеркальное отображение содержимого на экране
- Зеркальное отображение UIView
В магазине приложений есть традиционные монгольские приложения (вроде этого и этого), но я пока не нашел никого, кто бы делился своим исходным кодом, поэтому я не знаю, что они делают за кулисами для отображения текста. Я планирую сделать свой код открытым исходным кодом, чтобы в будущем другим было не сложно разрабатывать приложения для нескольких миллионов человек, которые читают традиционный монгольский язык. Любая помощь, которую вы можете оказать в этом начинании, будет высоко оценена не только мной, но и монгольским народом. Даже если вы сами не знаете, голосование по этому вопросу поможет сделать его более заметным.
Обновить
Ответ @sangonz по-прежнему отличный ответ, но я временно пометил его как принятый, потому что просто не мог заставить все работать. В частности:
- Включение прокрутки (либо путем внедрения пользовательского представления в представление прокрутки, либо путем создания подкласса UIScrollView). В проекте github @sangonz сказал, что это должно быть легко, но это было не для меня.
- Получение ретрансляции (а не растягивания) строк слова при изменении ориентации. Я думаю, что это не должно быть слишком сложно решить с помощью немного больше исследований.
- Почему текстовые строки не доходят до края представления? Внизу большой разрыв.
Как отсоединить NSTextStorage пользовательского вертикального представления от другого UITextView.(см. этот вопрос)
До этого момента я использовал оригинальный метод, который я предложил выше, но я действительно хочу получить что-то вроде того, что @sangonz предложил работать.
Я также сейчас рассматриваю альтернативные методы, такие как
- Использование базового текста, недостаток: похоже на изобретение колеса
- Недостаток использования WebKit: Apple больше не использует WebKit для своих
UITextView
2 ответа
Редактировать: Вот как я, наконец, сделал это.
Вот моя базовая реализация в 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.
Удачи!
Обновление: (изображение из проекта github)
Если вы собираетесь вращать текст, я бы предложил использовать макет справа налево, чтобы вы могли пропустить шаг зеркального отображения (и просто повернуть другой путь).
Вы должны иметь возможность просто установить метку / текстовое представление transform
имущество:
view.transform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(CGFloat(-M_PI_2)), view.bounds.width, view.bounds.height)
Вам нужно перевести после поворота, потому что вид вращается вокруг своего источника (в верхнем левом углу).
Хорошая новость заключается в том, что жесты и касания преобразуются одновременно в пиксели, поэтому элементы управления продолжают работать так, как вы ожидаете.