* Точно * вычисление высоты текста в Cocoa (для Mac, а не iOS)
Как я могу вычислить высоту строки в пределах определенной метки (NSTextField) для некоторой заданной фиксированной ширины?
Я погуглил разные методы и попробовал этот метод от Apple. Это работает, за исключением того, что высота становится на одну строку слишком короткой для более длинных строк. Таким образом, по-видимому, имеются некоторые неточности в настоящих способах.
У меня также была та же проблема с другим кодом, который я гуглил.
Есть ли у кого-нибудь здесь точный код для определения высоты текста (с учетом конкретной ширины)?
Ответы
Ответ 1
Я решил проблему, используя категорию NS (Attributed) String + Geometrics, представленную в http://www.sheepsystems.com/sourceCode/sourceStringGeometrics.html. В заголовочном файле этой категории есть хорошее объяснение того, как это работает. В частности, они упоминают, что для NSTextView вместо NSTextField следует использовать NSTextView, потому что практически невозможно получить точную высоту для последнего.
Таким образом, я заменил NSTextField на NSTextView. Во-первых, я сделал свой NSTextView похожим на свой NSTextField с помощью этого кода:
[textView setEditable:YES];
[textView insertText:someString];
[textView setFont:[NSFont fontWithName:@"Lucida Grande"
size:11] range:NSMakeRange(0,[someString length])];
[textView setEditable:NO];
[textView setSelectable:NO];
Затем я получил высоту с помощью этого кода:
NSDictionary *attributes
= [NSDictionary dictionaryWithObjectsAndKeys:
[textView font],NSFontAttributeName,nil];
NSAttributedString *attributedString
= [[NSAttributedString alloc] initWithString:
[textView string] attributes:attributes];
CGFloat height = [attributedString heightForWidth:
[textView frame].size.width];
Высота действительно оказывается точной для NSTextView.
Возможно, я опустил некоторые мелкие детали, но вы получите картину. Я надеюсь, что это поможет кому-то там.
Ответ 2
(решение в Swift находится в конце сообщения)
Я пробовал все эти методы, и никто не работал у меня. "Официальный" способ (как упоминалось в OP) в большинстве случаев отсутствовал для моего NSTextField
. Переключение на NSTextView
было невозможно из-за того, что XCode/IB всегда сбой после добавления "NSTextView в NSScrollView".
Короче говоря, я нашел этот простой способ определить высоту моего NSTextField
, но это может быть очень легко адаптировано к ширине.
CGFloat minHeight = [((NSTextFieldCell *)[yourTextField cell]) cellSizeForBounds:NSMakeRect(0, 0, YOUR_MAX_WIDTH, FLT_MAX)].height;
Этот код работал для каждого отдельного теста, который не сработал с другими методами. Я надеюсь, что это помогает кому-то. Это всегда заставляет меня чувствовать себя таким глупым, когда я беру 2 часа, чтобы найти решение, казалось бы, легкой проблемы.
SLIGHT EDIT. При ближайшем рассмотрении это работает, только если вы прочитали stringValue
NSTextField
, прежде чем я попрошу ячейку рассчитать ее высоту. Поэтому перед фактическим вычислением я добавил следующую бессмысленную строку:
[yourTextField setStringValue:yourTextField.stringValue];
Я знаю, что это действительно очень плохо, но на данный момент мне все равно. Я просто хочу надежное решение. Не стесняйтесь понизить меня или еще лучше: предлагайте лучшее решение.
Решение в Swift (спасибо iphaaw за то, что привлекли это мое внимание!)
myTextField.cell!.cellSizeForBounds(NSMakeRect(CGFloat(0.0), CGFloat(0.0), width, CGFloat(FLT_MAX))).height
Ответ 3
Спасибо, действительно, Ифау и Энчилада за это действительно крутое маленькое решение. Я нашел, что он работал так хорошо при установке высоты строк и т.д., Что я превратил iphaaw Swift в пару расширений NSTextField. Наслаждайтесь
extension NSTextField {
func bestheight(text: String, width: CGFloat) -> CGFloat {
self.stringValue = text
let getnumber = self.cell!.cellSizeForBounds(NSMakeRect(CGFloat(0.0), CGFloat(0.0), width, CGFloat(FLT_MAX))).height
return getnumber
}
}
extension NSTextField {
func bestwidth(text: String, height: CGFloat) -> CGFloat {
self.stringValue = text
let getnumber = self.cell!.cellSizeForBounds(NSMakeRect(CGFloat(0.0), CGFloat(0.0), CGFloat(FLT_MAX), height)).width
return getnumber
}
}
Я надеюсь, что кто-то найдет их полезными. рассматривает KGH
Ответ 4
Взгляните на ссылку на дополнение набора приложений NSString. Кажется, что – sizeWithAttributes:
или
– boundingRectWithSize:options:attributes:
могут делать то, что вы хотите.
Ответ 5
Ответ на энергичный кодинг работает так хорошо! Это действительно плохо? Кажется, он работает отлично. Наконец, потратив много часов на поиск других решений.
Вот мой Swift перевод кода:
myTextField.cell!.cellSizeForBounds(NSMakeRect(CGFloat(0.0), CGFloat(0.0), width, CGFloat(FLT_MAX))).height
Пожалуйста, не голосуйте за этот ответ. Вместо этого активируйте запись сильного кодирования.
Ответ 6
Это ответ ArtbyKGH для Swift 4+:
extension NSTextField {
func bestHeight(for text: String, width: CGFloat) -> CGFloat {
stringValue = text
let height = cell!.cellSize(forBounds: NSRect(x: 0, y: 0, width: width, height: .greatestFiniteMagnitude)).height
return height
}
func bestWidth(for text: String, height: CGFloat) -> CGFloat {
stringValue = text
let width = cell!.cellSize(forBounds: NSRect(x: 0, y: 0, width: .greatestFiniteMagnitude, height: height)).width
return width
}
}