* Точно * Расчет высоты текста в Какао (для Mac, а не iOS) - PullRequest
11 голосов
/ 01 апреля 2011

Как вычислить высоту строки в пределах определенной метки (NSTextField) для некоторой заданной фиксированной ширины?

Я погуглил различные методы и попробовал этот метод от Apple .Это работает, за исключением того, что высота становится на одну строку слишком короткой для более длинных строк.Таким образом, похоже, что в настоящих методах есть некоторые неточности.

У меня также была такая же проблема с другим кодом, который я гуглил.* код для поиска высоты текста (с учетом конкретной ширины)?

Ответы [ 6 ]

19 голосов
/ 02 апреля 2011

Я решил проблему, используя категорию NS (Attributed) String + Geometrics, предоставленную в http://www.sheepsystems.com/sourceCode/sourceStringGeometrics.html. В заголовочном файле этой категории есть хорошее объяснение того, как эти вещи работают. В частности, они упоминают, что следует использовать NSTextView вместо NSTextField, потому что практически невозможно получить точную высоту для последнего.

Таким образом, я заменил свой 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.

Возможно, я пропустил некоторые мелкие детали, но вы получите картину. Я надеюсь, что это поможет кому-то там.

7 голосов
/ 11 августа 2013

(решение в Swift находится в конце поста)

Я перепробовал все эти методы, и ни один из них не работал для меня.«Официальный» путь (как упомянуто OP) большую часть времени был для моего NSTextField.Переключение на NSTextView было невозможно из-за сбоя XCode / IB всегда после добавления «NSTextView в NSScrollView».

Короче говоря, я нашел этот простой способ определить высотуmy NSTextField, но это может быть очень легко адаптировано к ширине.

CGFloat minHeight = [((NSTextFieldCell *)[yourTextField cell]) cellSizeForBounds:NSMakeRect(0, 0, YOUR_MAX_WIDTH, FLT_MAX)].height;

Этот код работал для каждого отдельного теста, который не удался с другими методами.Я надеюсь, что это помогает кому-то.Я всегда чувствую себя чертовски глупо, когда беру 2 часа, чтобы найти решение, казалось бы, легкой проблемы.

МЕДЛЕННОЕ ИЗМЕНЕНИЕ : При ближайшем рассмотрении это работает, только если вы прочитаете stringValue из NSTextField, прежде чем я попрошу ячейку рассчитать ее высоту.Поэтому я добавил следующую бессмысленную строку перед фактическим расчетом:

[yourTextField setStringValue:yourTextField.stringValue];

Я знаю, что это действительно очень плохо, но на данный момент мне все равно,Я просто хочу надежное решение.Не стесняйтесь понизить меня или еще лучше : предложите лучшее решение.


Решение в Swift (спасибо iphaaw за то, что вы обратили на это мое внимание!)

myTextField.cell!.cellSizeForBounds(NSMakeRect(CGFloat(0.0), CGFloat(0.0), width, CGFloat(FLT_MAX))).height
4 голосов
/ 24 июля 2016

Спасибо действительно iphaaw и Enchilada за это действительно классное маленькое решение. Я обнаружил, что он работал так хорошо при настройке высоты строк и т. Д., Что я преобразовал Swift iphaaw в пару расширений 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

2 голосов
/ 01 апреля 2011

Взгляните на Справочник по дополнениям NSString Application Kit . Кажется, – sizeWithAttributes: или – boundingRectWithSize:options:attributes: может делать то, что вы хотите.

0 голосов
/ 21 мая 2019

Это ответ 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
    }
}
0 голосов
/ 17 августа 2015

Ответ Vigorouscoding работает так хорошо!Это действительно плохо?Кажется, работает отлично.Наконец, проведя много часов, пытаясь найти другие решения.

Вот мой Swift перевод кода:

myTextField.cell!.cellSizeForBounds(NSMakeRect(CGFloat(0.0), CGFloat(0.0), width, CGFloat(FLT_MAX))).height

Пожалуйста, не голосуйте за этот ответ.Вместо этого используйте запись Upvote vigorouscoding.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...