Autolayout: как работает функция fitSize?

Я создал подкласс NSTextField , который изменяет его высоту в соответствии с текстом, который он содержит. Теперь я хочу вставить его в другое представление ( NSTableCellView ) и изменить размер представления в соответствии с высотой текстового поля.

Я хочу использовать метод - (NSSize) fitSize для NSView , но, к сожалению, он, похоже, не вызывает метод fittingSize своих подзонов, их метод intrinsicContentSize .

Вот код, который я использую для подкласса NSTableCellView :

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setTranslatesAutoresizingMaskIntoConstraints:NO];
        self.expandingTextField = [[JSExpandingTextField alloc] init];
        [self addSubview:self.expandingTextField];
        [self removeConstraints:self.constraints];
        NSDictionary *row = NSDictionaryOfVariableBindings(expandingTextField);
        [self addConstraints:[NSLayoutConstraint
                              constraintsWithVisualFormat:@"V:|-20-[expandingTextField]-28-|"
                              options:0 metrics:nil views:row]];
    }

    return self;
}

- (NSSize)fittingSize
{
    return [super fittingSize];
}

Я переопределяю метод fittingSize здесь только для того, чтобы поставить точку останова или NSLog .

Вот код делегата представления таблицы, который обеспечивает высоту ячейки таблицы:

- (JSDynamicTableCellView *)dummyCell
{
    if (!_dummyCell) {
        _dummyCell = [[JSDynamicTableCellView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 100, 100)];
    }
    return _dummyCell;
}

- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
    self.dummyCell.expandingTextField.stringValue = @"Test";
    NSLog(@"Cell size %@",NSStringFromSize([self.dummyCell fittingSize]));
    return [self.dummyCell fittingSize].height;
}

Все это всегда возвращает высоту для dummyCell из 69 независимо от размера расширяющегося текстового поля в ячейке.

Возникает вопрос: как метод «fitSize» определяет размер его подзонов? Должны ли они называть их методы «fitSize» или «ntrinsicContentSize» или это что-то еще?

2
добавлено отредактировано
Просмотры: 1
de
Я не уверен, что понимаю, что вы делаете - разве вы не ожидаете, что он вернет тот же размер, так как вы даете ему ту же строку «Тест», и он использует это для расчета?
добавлено автор rdelmar, источник
Извините, я имел в виду, что он возвращает тот же размер независимо от того, какую строку я ему даю. Если я назначаю более длинную строку, я могу видеть, что текстовое поле правильно изменяет размер, чтобы соответствовать строке, но метод 'fittingSize' ячейки все равно возвращает ту же высоту.
добавлено автор Jacopo, источник

2 ответы

fittingSize is conceptually simple. It collects all of the constraints that have been added to your view or one of its subviews (recursively), and then it determines the size of the view based on only those constraints. You can think of it as determining the smallest size that is big enough to show the contents of that view hierarchy.

Edit:We need to be quite clear here. fittingSize returns minimum values and will return 0 for any dimension that is not fully specified. For example, if the vertical constraint tying a view to the bottom of its superview is omitted then the fitted height will be 0.

Edit: I just realized what you're probably running into: fittingSize is computing the text field as if it were just one long line, that does not wrap. You can confirm this by giving it a string value with one or more newlines: now the height should be bigger!

Итак, как это исправить? Ну, у вас есть текстовое поле, и вы даете ему содержимое, и вы хотите узнать его высоту. Но если текстовое поле обертывается, высота будет зависеть от ширины: сделайте ее более узкой, и текстовое поле будет перенесено на большее количество строк, поэтому оно будет потреблять больше высоты. Поэтому, чтобы измерить предпочтительную высоту для текстового поля для обертывания, вы должны указать ширину для ее обертывания.

В OS X Mountain Lion и iOS 6 вы можете сделать это с помощью метода [NSTextField setPreferredMaxLayoutWidth:] . Например, если вы хотите вычислить высоту на основе ширины 100, вы должны вызвать [textField setPreferredMaxLayoutWidth: 100] ; теперь fittingSize будет сообщать о высоте для текстового поля на основе его обертывания шириной 100.

Кстати, это плохая идея:

[self removeConstraints:self.constraints];

Поскольку он удаляет ограничения, добавленные другими частями системы. Вы должны только удалить ограничение, которое вы создали, либо в коде, либо в IB.

7
добавлено
Спасибо за предложение, но, к сожалению, он не работает. Я удалил строку, удалив все ограничения, и добавил «[_dummyCell.expandingTextField setPreferredMaxLayoutWidth: 100.0]; к экземпляру '_dummyCell'. Метод «fitSize» по-прежнему возвращает одно и то же значение независимо от длины строки, в которой я проходил. Моя проблема кажется более глубокой. Я могу поместить логические выходы и точки останова в методах «fitSize» и «intrinsicContentSize» текстового поля, и я вижу, что они никогда не вызываются. В то же время я вижу, что текстовое поле действительно является подразделением '_dummyCell'
добавлено автор Jacopo, источник
Я могу легко решить проблему, вручную вызвав метод «intrinsicContentSize» для каждого поднабора «_dummyCell» и вычислив его высоту, но я думал, что ограничения должны сделать это для меня.
добавлено автор Jacopo, источник
Поиграв немного больше, я узнал, что настройка «preferredMaxWidthLayout» текстового поля работает только для не редактируемого текстового поля. Для редактируемого текстового поля свойство просто игнорируется.
добавлено автор Jacopo, источник
Очень ценный момент Якопо. Спасибо. спасли меня много времени
добавлено автор jiminybob99, источник

Попробуйте это сделать (для этого щелкните на фоне xib или раскадровки)

enter image description here

6
добавлено
Я не могу этого сделать. Методы 'fittingSize' и 'intrinsicContentSize', которые я пытаюсь использовать, являются частью системы автоматического макета. Предполагается, что метод «fitSize» учитывает ограничения.
добавлено автор Jacopo, источник
ой. они не знают, как помочь. Прости
добавлено автор OnkaPlonka, источник