Подтвердить что ты не робот

Как разрешить NSTextField расти с текстом в автоматическом макете?

Автомакет в Lion должен сделать достаточно простым, чтобы текстовое поле (и, следовательно, ярлык) увеличивалось с сохраненным текстом.

Текстовое поле настроено на обертку в Interface Builder.

Что такое простой и надежный способ сделать это?

4b9b3361

Ответ 1

Метод intrinsicContentSize в NSView возвращает то, что сам взгляд рассматривает как его собственный размер содержимого.

NSTextField вычисляет это без учета свойства wraps своей ячейки, поэтому он будет сообщать размеры текста, если он выложен в одной строке.

Следовательно, пользовательский подкласс NSTextField может переопределить этот метод, чтобы вернуть лучшее значение, например, предоставленное методом cell cellSizeForBounds::

-(NSSize)intrinsicContentSize
{
    if ( ![self.cell wraps] ) {
        return [super intrinsicContentSize];
    }

    NSRect frame = [self frame];

    CGFloat width = frame.size.width;

    // Make the frame very high, while keeping the width
    frame.size.height = CGFLOAT_MAX;

    // Calculate new height within the frame
    // with practically infinite height.
    CGFloat height = [self.cell cellSizeForBounds: frame].height;

    return NSMakeSize(width, height);
}

// you need to invalidate the layout on text change, else it wouldn't grow by changing the text
- (void)textDidChange:(NSNotification *)notification
{
    [super textDidChange:notification];
    [self invalidateIntrinsicContentSize];
}

Ответ 2

Swift 4

Редактируемый Авторазмер NSTextField

Основано на посте Питера Лапису Objective-C

Подкласс NSTextField, добавьте код ниже.

override var intrinsicContentSize: NSSize {
    // Guard the cell exists and wraps
    guard let cell = self.cell, cell.wraps else {return super.intrinsicContentSize}

    // Use intrinsic width to jive with autolayout
    let width = super.intrinsicContentSize.width

    // Set the frame height to a reasonable number
    self.frame.size.height = 750.0

    // Calcuate height
    let height = cell.cellSize(forBounds: self.frame).height

    return NSMakeSize(width, height);
}

override func textDidChange(_ notification: Notification) {
    super.textDidChange(notification)
    super.invalidateIntrinsicContentSize()
}

Установка self.frame.size.height в "разумное число" позволяет избежать некоторых ошибок при использовании FLT_MAX, CGFloat.greatestFiniteMagnitude или больших чисел. Ошибки возникают во время работы, когда пользователь выбирает выделение текста в поле, они могут перетаскивать прокрутку вверх и вниз в бесконечность. Кроме того, когда пользователь вводит текст, NSTextField отключается до тех пор, пока пользователь не завершит редактирование. Наконец, если пользователь выбрал NSTextField и затем пытается изменить размер окна, если значение self.frame.size.height слишком велико, окно будет зависать.

Ответ 3

Принятый ответ основан на управлении intrinsicContentSize, но это может быть не обязательно во всех случаях. Autolayout будет увеличиваться и уменьшать высоту текстового поля, если (a) вы даете текстовое поле a preferredMaxLayoutWidth и (b) создаете поле не editable. Эти шаги позволяют текстовому полю определять его внутреннюю ширину и вычислять высоту, необходимую для автоматического отключения. Подробнее см. этот ответ и этот ответ.

Еще более неясно, из зависимости от атрибута текстового поля editable, что автоопределение будет нарушено, если вы используете привязки в поле и не можете очистить параметр Conditionally Sets Editable.