IOS: многострочный UILabel в автоматическом макете
У меня возникли проблемы с попыткой добиться очень простого поведения макета с помощью Auto Layout. Контроллер моего вида выглядит следующим образом: IB:
Верхняя метка - это ярлык заголовка, я не знаю, сколько строк оно будет. Мне нужен ярлык заголовка для отображения всех строк текста. Мне также нужны два других ярлыка и небольшое изображение, которое будет выложено прямо под названием, каким бы высоким оно ни было. Я установил ограничения вертикального расстояния между метками и маленьким изображением, а также ограничение верхнего расстояния между меткой заголовка и его супервидом и ограничение нижнего интервала между маленьким изображением и его супервидом. Белый UIView не имеет ограничения по высоте, поэтому он должен растягиваться вертикально, чтобы содержать его подпункты. Я установил количество строк для метки заголовка равным 0.
Как я могу получить метку заголовка для изменения размера, чтобы соответствовать количеству строк, необходимых для строки? Я понимаю, что я не могу использовать методы setFrame, потому что я использую Auto Layout. И я должен использовать автоматический макет, потому что мне нужны эти другие представления, чтобы оставаться ниже метки названия (следовательно, ограничений).
Как я могу это сделать?
Ответы
Ответ 1
Используйте -setPreferredMaxLayoutWidth
на UILabel
а UILabel
должна обрабатываться автоматически.
[label setPreferredMaxLayoutWidth:200.0];
См. Документацию UILabel для предпочитаемого MaxLayoutWidth.
Обновить:
Нужно только установить ограничение height
в раскадровке на значение " Greater than or equal to
, нет необходимости устанавливать setPreferredMaxLayoutWidth.
Ответ 2
Разверните свою метку, задав количество строк до 0, а также, что более важно, для автоматической установки высоты набора до >= x. Авто макет сделает все остальное. Вы также можете использовать другие элементы, основанные на предыдущем элементе, чтобы правильно позиционировать.
Ответ 3
Источник: http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html
Внутренний размер содержимого многострочного текста
Внутренний размер содержимого UILabel и NSTextField неоднозначен для многострочного текста. Высота текста зависит от ширины линий, которая еще не определена при решении ограничений. Чтобы решить эту проблему, оба класса имеют новое свойство, называемое preferredMaxLayoutWidth, которое определяет максимальную ширину линии для вычисления внутреннего размера содержимого.
Поскольку мы обычно не знаем этого значения заранее, нам нужно сделать двухэтапный подход, чтобы получить это право. Сначала мы даем авто макет выполнить свою работу, а затем мы используем результирующий фрейм в макете, чтобы обновить предпочтительную максимальную ширину и шаблон триггера снова.
- (void)layoutSubviews
{
[super layoutSubviews];
myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
[super layoutSubviews];
}
Первый вызов [super layoutSubviews] необходим для того, чтобы метка получила свой набор кадров, а второй вызов необходим для обновления макета после изменения. Если мы опустим второй вызов, мы получим ошибку NSInternalInconsistencyException, потому что weve внесло изменения в макетный проход, который требует обновления ограничений, но мы еще не запускали макет.
Мы также можем сделать это в самом подклассе метки:
@implementation MyLabel
- (void)layoutSubviews
{
self.preferredMaxLayoutWidth = self.frame.size.width;
[super layoutSubviews];
}
@end
В этом случае нам не нужно сначала называть [super layoutSubviews], потому что при вызове layoutSubviews мы уже имеем фрейм на самой этикетке.
Чтобы выполнить эту настройку с уровня контроллера, заглянем в viewDidLayoutSubviews. В этот момент рамки первого прохода Auto Layout уже установлены, и мы можем использовать их для установки предпочтительной максимальной ширины.
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
[self.view layoutIfNeeded];
}
Наконец, убедитесь, что у вас нет явного ограничения высоты на ярлыке с более высоким приоритетом, чем приоритет сопротивления сжатию содержимого. В противном случае он превзойдет расчетную высоту содержимого. Обязательно проверьте все ограничения, которые могут повлиять на высоту метки.
Ответ 4
Я просто сражался с этим точным сценарием, но с довольно большим количеством просмотров, которые необходимо было изменить и по мере необходимости изменить. Это сводило меня с ума, но я, наконец, понял это.
Здесь ключ: Interface Builder любит бросать лишние ограничения при добавлении и перемещении просмотров, и вы можете не заметить. В моем случае у меня было представление на полпути вниз, у которого было дополнительное ограничение, которое указывало размер между ним и его супервидом, в основном привязывая его к этой точке. Это означало, что ничто выше этого не могло бы изменить размер больше, потому что это противоречило бы этому ограничению.
Легкий способ сказать, если это так, - это изменить размер метки вручную. Позволяет ли IB вам расти? Если это так, сделайте этикетки ниже, как вы ожидаете? Перед изменением размера убедитесь, что у вас есть оба эти флажка, чтобы увидеть, как ваши ограничения будут перемещать ваши представления:
Если представление застряло, следуйте представлениям ниже него и убедитесь, что у одного из них нет верхнего пространства для ограничения супервизора. Затем просто убедитесь, что для вашего номера строк для метки установлено значение 0, и он должен позаботиться об остальном.
Ответ 5
Я нахожу, что вам нужно следующее:
- Верхнее ограничение
- Ведущее ограничение (например, левая сторона)
- Возвращаемое ограничение (например, правая сторона)
- Установите приоритет обхода контента, горизонтальный и низкий, чтобы он заполнил заданное пространство, если текст короткий.
- Установите сопротивление сжатию содержимого, горизонтальное на низкое, поэтому оно будет обертываться вместо того, чтобы попытаться стать шире.
- Задайте количество строк в 0.
- Установите режим разрыва строки на перенос слов.
Ответ 6
Ни одно из различных решений, найденных во многих разделах этой темы, отлично работало для моего случая (x динамических многострочных меток в ячейках динамического представления таблицы).
Я нашел способ сделать это:
После того, как вы установили ограничения на свой ярлык и задали его многострочное свойство равным 0, создайте подкласс UILabel; Я назвал мой AutoLayoutLabel:
@implementation AutoLayoutLabel
- (void)layoutSubviews{
[self setNeedsUpdateConstraints];
[super layoutSubviews];
self.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds);
}
@end
Ответ 7
У меня есть UITableViewCell с надписью для обертывания текста. Я обработал текстовую оболочку следующим образом.
1) Установите ограничения UILabel следующим образом.
2) Установите номер. строк до 0.
3) Добавлена ограничение высоты UILabel для UITableViewCell.
@IBOutlet weak var priorityLabelWidth: NSLayoutConstraint!
4) В UITableViewCell:
priorityLabel.sizeToFit()
priorityLabelWidth.constant = priorityLabel.intrinsicContentSize().width+5
Ответ 8
Один из способов сделать это...
По мере увеличения длины текста попытайтесь изменить (уменьшить) шрифт текста ярлыка, используя
Label.adjustsFontSizeToFitWidth = YES;