Autolayout:fittingSize如何正常工作?

Jac*_*opo 3 macos cocoa objective-c nslayoutconstraint

我创建了一个子类,NSTextField根据它包含的文本更改其高度.我现在想在另一个视图(an NSTableCellView)中插入它,并根据文本字段的高度调整视图大小.

我想使用-(NSSize)fittingSize方法,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];
}
Run Code Online (Sandbox Code Playgroud)

我在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;
}
Run Code Online (Sandbox Code Playgroud)

所有这些总是返回dummyCell为69的高度,与单元格中扩展文本字段的大小无关.

问题是:'fittingSize'方法如何计算其子视图的大小?它应该调用'fittingSize'还是'ntrinsicContentSize'方法还是其他方法?

rid*_*ish 9

fittingSize在概念上很简单.它收集已添加到视图或其子视图之一(递归)的所有约束,然后它仅基于这些约束确定视图的大小.您可以将其视为确定足以显示该视图层次结构内容的最小大小.

编辑:我们需要在这里很清楚.fittingSize返回最小值,对于未完全指定的任何维度,将返回0.例如,如果省略了将视图绑定到其超视图底部的垂直约束,则拟合高度将为0.

编辑:我刚刚意识到你可能遇到的是:fittingSize计算文本字段就好像它只是一条长线,没有包装.您可以通过给它一个带有一个或多个换行符的字符串值来确认这一点:现在高度应该更大!

那么如何解决这个问题呢?好吧,你有一个文本字段,你给它内容,你想知道它的高度.但是如果文本字段包装,高度将取决于宽度:使其更窄,文本字段将换行更多行,因此它将消耗更多高度.因此,为了测量包装文本字段的首选高度,您必须告诉它要包装的宽度.

在OS X Mountain Lion和iOS 6上,您可以使用该[NSTextField setPreferredMaxLayoutWidth:]方法执行此操作.例如,如果要根据宽度100计算高度,则可以调用[textField setPreferredMaxLayoutWidth:100]; 现在fittingSize将报告文本字段的高度,基于它以100的宽度包装.

顺便说一句,这是一个坏主意:

[self removeConstraints:self.constraints];
Run Code Online (Sandbox Code Playgroud)

因为它删除了系统其他部分添加的约束.您应该只删除您在代码或IB中创建的约束.

  • 再玩一下后,我发现设置文本字段的'preferredMaxWidthLayout'仅适用于不可编辑的文本字段.对于可编辑的文本字段,将简单地忽略该属性. (2认同)