Как мне получить UIView, который отображает текст, чтобы вести себя как UILabel при изменении границ?

У меня есть UIView, в котором мне нужно рисовать текст в drawRect:

- (void)drawRect:(CGRect)rect {
    ...
    [@"some text" drawAtPoint:somePoint withFont:someFont];
    ...
}

Поскольку текст требует специального форматирования, я не могу просто использовать UILabel.

Он выглядит нормально, пока я не поверну устройство. Затем размер моего пользовательского UIView изменяется (в методе layoutSubviews родительского представления), и текст растягивается в одном направлении и сжимается в другом.

Когда я заменяю свое представление на UILabel, текст всегда выглядит великолепно, даже когда границы представления изменяются.

Как я могу заставить свое представление демонстрировать то же поведение, что и UILabel?

Некоторые вещи, которые я изучил, но еще не добился успеха:

  • Установите для слоя needDisplayOnBoundsChange представления значение YES.
  • Установите для contentStretch представления значение CGRectZero.
  • Вызовите setNeedsDisplay в layoutSubviews моего представления.

Может быть, я не делаю одну из этих вещей правильно. Кто-нибудь еще столкнулся с этим?

Обновление: Как рекомендовано в ответе Джеймса Хаддлстона, я установил для свойства contentMode представления значение UIViewContentModeRedraw, что частично помогло мне в этом. Текст теперь отображается правильно в конце анимации. Однако в начале анимации текст сжимается/растягивается, чтобы соответствовать конечным размерам, а затем не сжимается/не растягивается в ходе анимации. Это не относится к UILabel.


person Hilton Campbell    schedule 16.10.2010    source источник
comment
Простите, а как вы рисуете текст?   -  person tia    schedule 16.10.2010
comment
tia: Хороший вопрос, я должен был объяснить это. Я уточнил в вопросе.   -  person Hilton Campbell    schedule 16.10.2010
comment
6 лет спустя. Вы нашли решение для этого (при использовании собственного пользовательского класса, который напрямую наследуется от UIView)?   -  person bartzy    schedule 05.03.2016
comment
Я так не думаю :) Это, вероятно, что-то простое, но я не стал вникать в это намного дальше.   -  person Hilton Campbell    schedule 07.03.2016


Ответы (4)


Попробуйте установить для свойства contentMode вашего представления значение UIViewContentModeRedraw.

person James Huddleston    schedule 16.10.2010
comment
Хорошо, я не знал, что это было спрятано там с другими режимами контента. С contentMode = UIViewContentModeRedraw текст теперь отображается правильно в конце поворота. Тем не менее, текст деформируется во время перехода. Любой способ избежать этого? - person Hilton Campbell; 16.10.2010
comment
Не то, что я знаю из. Я думаю, что анимация работает так, что ваш метод drawRect рисует вид после вращения с размером после вращения, а затем он масштабирует этот вид на лету (без повторного вызова drawRect) для создания анимации. Таким образом, если размер вашего вида после вращения меньше, чем размер до вращения, он по существу нарисует ваш вид в этом меньшем размере, но затем увеличит его (и, возможно, пикселизирует) в качестве отправной точки для рисования анимации. . Конечно, любые изменения макета также будут анимированы. Имеет ли это смысл с тем, что вы видите? - person James Huddleston; 16.10.2010
comment
Да, это именно то, что я вижу. Дело в том, что UILabel этого не делает. Он просто сразу же изменяет размер и позиционирует вид в кадре после поворота и соответствующим образом рисует текст. Он вообще не анимируется. - person Hilton Campbell; 16.10.2010
comment
Возможно, UILabel подвергается особой обработке во время анимации. Извините... Я не знаю обходного пути для пользовательского рисования. - person James Huddleston; 16.10.2010

Кажется, это работает нормально:

self.contentMode = UIViewContentModeRedraw;
self.contentStretch = CGRectMake(1, 1, 0.5, 0.5);

Затем убедитесь, что нижний правый пиксель является цветом фона. Для этого я поместил один пиксель заполнения вокруг содержимого представления. Похоже, что UILabel не имеет ограничения в один пиксель, поэтому он должен делать что-то другое. Но насколько я могу судить, это имеет тот же эффект.

person Hilton Campbell    schedule 03.01.2011

Используйте UIWebView

Звучит немного чересчур, но кажется, что рекомендуемый способ получить отформатированный текст более сложен, чем может справиться UILabel.

person deanWombourne    schedule 04.01.2011
comment
Да, слишком много для моего варианта использования :). Тем более, что у меня все работает отлично, кроме этой одной детали. - person Hilton Campbell; 05.01.2011

Существует некоторый исходный код, созданный Кевином Баллардом, который называется FontLabel. (код .google.com)

Хорошая вещь в этом, это подклассы UILabel, и вы можете использовать свой собственный шрифт;)

// РЕДАКТИРОВАТЬ: хорошо, как сказано, я обновлю свой ответ, чтобы рекомендовать создание подкласса UILabel "to get all the UILabel goodness" ^^

person Community    schedule 04.01.2011
comment
Однако UILabel уже позволяет вам использовать собственный шрифт. Это для использования с cocos2d, который рендерится в OpenGL. Спасибо хоть. - person Hilton Campbell; 05.01.2011
comment
нет, вы не можете рисовать шрифты, которых нет во фреймворке. с этой структурой вы также можете рисовать UILabel с помощью пользовательских шрифтов, которые вы вручную включили в свой проект, скажем, mySampleFont.ttf;) // изменить: или даже это возможно с UILabel по умолчанию? если да, то дайте мне пример кода - person ; 05.01.2011
comment
Вы правы, я неправильно понял, что вы имели в виду, используя свой собственный шрифт. До iOS 3.2 и 4.0 вы не могли использовать свой собственный шрифт. Вы можете с более новыми версиями iOS, но я еще не пробовал. - person Hilton Campbell; 05.01.2011
comment
Итак, я сначала отклонил этот ответ, но... оказывается, я могу просто создать подкласс UILabel для своего пользовательского представления и получить эффект, который я ищу! Это работает отлично. Ну, после того, как я установил contentMode = UIViewContentModeTopLeft, так как иначе это выглядело забавно в моей конкретной ситуации. iPortable: обновите свое решение с рекомендацией просто подкласса UILabel, чтобы получить все преимущества UILabel, и я награжу вас наградой. Я действительно хотел бы разделить награду между всеми ответившими :(. - person Hilton Campbell; 05.01.2011
comment
почему ты снял галочку с ответа? Что-то не так? вероятно, потому что я проголосовал за всех остальных? - person ; 05.01.2011