Как изменить размер UILabel, изменив только высоту, а не ширину?
[self.Review sizeToFit];
Результат перед sizeToFit:
NSStringFromCGRect(self.Review.frame): {{90, 20}, {198, 63}}
Результат После sizeToFit:
NSStringFromCGRect(self.Review.frame): {{90, 20}, {181, 45}}
Я хочу, чтобы ширина осталась прежней. Я просто хочу изменить высоту. Автомастер
(lldb) po self.Review
(UILabel *) $1 = 0x08bb0fe0 <UILabel: 0x8bb0fe0; frame = (90 20; 181 45); text = 'I'm at Mal Taman Anggrek ...'; clipsToBounds = YES; opaque = NO; autoresize = LM+RM+H; userInteractionEnabled = NO; layer = <CALayer: 0x8bb68b0>>
Я знаю, что есть способ сделать это с помощью:
Как настроить и сделать ширину UILabel в соответствии с размером текста?
Ответы либо странные (нам нужно пополнить информацию о шрифте). Или неясно.
Вам также необходимо определить максимальную ширину и сообщить своей программе что делать, если sizeToFit дает вам ширину больше этого максимума.
Я использую странное решение использования sizeWithFont
. Странно, потому что UILabel уже знает шрифт в ярлыке.
Вообще-то, как ведет себя режим sizeToFit? Как он решает, нужен ли нам более тонкий или более высокий UILabel?
Ответы
Ответ 1
Вот как это делается. Поскольку метка уже содержит информацию о шрифте, включая ее в этом вызове метода, тривиально.
CGSize size = [label.text sizeWithFont:label.font
constrainedToSize:CGSizeMake(maxWidth, MAXFLOAT)
lineBreakMode:UILineBreakModeWordWrap];
CGRect labelFrame = label.frame;
labelFrame.size.height = size.height;
label.frame = labelFrame;
Быстрая версия с использованием более современных boundingRectWithSize
:
let maxHeight = CGFloat.infinity
let rect = label.attributedText?.boundingRectWithSize(CGSizeMake(maxWidth, maxHeight),
options: .UsesLineFragmentOrigin, context: nil)
var frame = label.frame
frame.size.height = rect.size.height
label.frame = frame
Ответ 2
Вы можете добиться того же результата с помощью sizeThatFits.
CGSize size = [label sizeThatFits:CGSizeMake(label.frame.size.width, CGFLOAT_MAX)];
CGRect frame = label.frame;
frame.size.height = size.height;
label.frame = frame;
Или, альтернативно, с sizeToFit.
CGRect frame = label.frame;
[label sizeToFit];
frame.size.height = label.frame.size.height;
label.frame = frame;
Ответ 3
sizeToFit отлично работает. Единственная проблема заключается в том, что он основан на текущем размере элемента управления.
Например, если вы перебираете ячейки таблицы с меткой, метка может быть уменьшена по ширине в предыдущей ячейке, и поэтому вызов sizeToFit может выглядеть ненадежным.
Просто reset исходная ширина вашего элемента управления перед отправкой сообщения sizeToFit.
Ответ 4
Я думаю, вы не должны использовать методы NSString
size...
, UILabel
уже имеет API для этого, как указывает @vatrif (который, вероятно, использует только методы NSString
).
Тем не менее, я думаю, что API UILabel
можно было бы улучшить. Вот почему я считаю, что категория будет самым элегантным решением:
// UILabel+Resize.h
@interface UILabel (Resize)
- (void)sizeToFitHeight;
@end
// UILabel+Resize.m
@implementation UILabel (Resize)
- (void)sizeToFitHeight {
CGSize size = [self sizeThatFits:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)];
CGRect frame = self.frame;
frame.size.height = size.height;
self.frame = frame;
}
@end
Только одно: я не уверен в соответствующем имени для этого метода:
- sizeToFitHeight?
- heightToFit?
Комментарии очень ценятся, спасибо!
Ответ 5
Ответ на 2017...
c = CGSize (ширина: ваша ширина, высота: CGFloat.greatestFiniteMagnitude)
result = sizeThatFits (c).height
Итак...
let t = .... your UITextView
let w = .... your known width of the item
let trueHeight = t.sizeThatFits(
CGSize(width: t, height: CGFloat.greatestFiniteMagnitude)).height
Что это.
Очень часто вы хотите знать разницу высот по сравнению с "нормальной" однострочной записью.
Это особенно важно, если вы создаете какие-то ячейки, которые не имеют ничего общего с UTableView (скажем, какое-то представление пользовательского стека). Вы должны установить высоту вручную в какой-то момент. На своем раскадровке создайте его по своему усмотрению, используя образец текста любой короткой строки (например, "А" ), которая, конечно же, будет иметь только одну строку в любой нормальной ситуации. Затем вы делаете что-то вроде этого...
func setTextWithSizeCorrection() { // an affaire iOS
let t = .... your UITextView
let w = .... your known width of the item
let oneLineExample = "A"
let actualText = yourDataSource[row].description.whatever
// get the height as if with only one line...
experimental.text = oneLineExample
let oneLineHeight = t.sizeThatFits(
CGSize(width: w, height: CGFloat.greatestFiniteMagnitude)).height
// get the height with the actual long text...
// (note that usually, you do not want a one-line minimum)
experimental.text = (actualText == "") ? oneLineExample : actualText
let neededHeight = t.sizeThatFits(
CGSize(width: w, height: CGFloat.greatestFiniteMagnitude)).height
experimental.text = actualText
let delta = neededHeight - oneLineHeight
set the height of your cell, or whatever it is(standardHeight + delta)
}
Конечная точка: одна из действительно глупых вещей в iOS заключается в том, что UITextView имеет странный вид поля внутри него. Это означает, что вы не можете просто переключаться между UITextViews и ярлыками; и это вызывает много других проблем. Apple не исправила эту проблему с момента написания. Устранить проблему сложно: обычно используется следующий подход:
@IBDesignable class UITextViewFixed: UITextView {
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
func setup() {
textContainerInset = UIEdgeInsets.zero;
textContainer.lineFragmentPadding = 0;
}
}
Сломанный, непригодный UITextView от Apple...
![введите описание изображения здесь]()
UITextViewFixed
, который в большинстве случаев является приемлемым исправлением:
![введите описание изображения здесь]()
(Желтый добавлен для ясности.)
Ответ 6
Согласованный API выиграет от этого добавления. Сделайте вашу жизнь проще и добавьте расширение к классу UILabel в Swift следующим образом:
extension UILabel {
func sizeToFitHeight() {
let size:CGSize = self.sizeThatFits(CGSizeMake(self.frame.size.width, CGFloat.max))
var frame:CGRect = self.frame
frame.size.height = size.height
self.frame = frame
}
}
Ответ 7
ФИКСИРОВАННОЕ РЕШЕНИЕ ДЛЯ SWIFT 3
Используйте CGFloat.greatestFiniteMagnitude
для maxHeight.
let size = CGSize.init(width: yourLabel.frame.size.width,
height: CGFloat.greatestFiniteMagnitude)
let rect = errorLabel.attributedText?.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil)
var frame = errorLabel.frame
frame.size.height = (rect?.size.height)!
errorLabel.frame = frame
ИЛИ Создать расширение UIlabel
и метод вызова yourLabel. sizeToFitHeight()
extension UILabel {
func sizeToFitHeight() {
let maxHeight : CGFloat = CGFloat.greatestFiniteMagnitude
let size = CGSize.init(width: self.frame.size.width, height: maxHeight)
let rect = self.attributedText?.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil)
var frame = self.frame
frame.size.height = (rect?.size.height)!
self.frame = frame
}
}
Ответ 8
Легкое расширение для этой задачи для Swift 3.
extension UILabel {
func sizeToFitHeight() {
let size: CGSize = self.sizeThatFits(CGSize.init(width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
var frame:CGRect = self.frame
frame.size.height = size.height
self.frame = frame
}
}
Ответ 9
Свифт 3 версии Mundi ответ:
let maxHeight: CGFloat = 10000
let rect = label.attributedText!.boundingRect(with: CGSize(width: maxWidth, height: maxHeight),
options: .usesLineFragmentOrigin,
context: nil)
var frame = labe.frame
frame.size.height = rect.size.height
label.frame = frame
Ответ 10
Я считаю, что у меня есть намного более простое решение:
let oldWidth = self.frame.size.width
label.sizeToFit()
label.frame.size.width = oldWidth
Просто сохраните прежнюю ширину, sizeToFit()
применимо как к ширине, так и к высоте, затем сбросьте ширину обратно к старому значению, оставив только измененную высоту метки.