Autolayout: Wie funktioniert die Anpassung genau?

Ich habe eine Unterklasse von NSTextField erstellt, die ihre Höhe entsprechend dem darin enthaltenen Text ändert. Ich möchte es nun in eine andere Ansicht (ein NSTableCellView ) einfügen und die Größe der Ansicht entsprechend der Höhe des Textfelds anpassen.

Ich möchte die - (NSSize) fittingSize -Methode von NSView verwenden, aber leider scheint sie nicht die Methode fittingSize ihrer Unteransichten noch aufzurufen ihre intrinsicContentSize -Methode.

Hier ist der Code, den ich für die Unterklasse NSTableCellView verwende:

- (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];
}

Ich überschreibe die Methode fittingSize hier nur, um einen Haltepunkt oder einen NSLog zu setzen.

Hier ist der Code des Tabellenansichtsdelegaten, der die Höhe der Tabellenzelle angibt:

- (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;
}

All dies liefert immer eine Höhe für dummyCell von 69 unabhängig von der Größe des expandierenden Textfelds in der Zelle.

Die Frage ist: Wie berechnet die Methode 'fittingSize' die Größe ihrer Untersichten? Sollte es ihre "FittingSize" - oder "NtrinsicContentSize" -Methode aufrufen oder ist es etwas anderes?

2
hinzugefügt bearbeitet
Ansichten: 1
nl ja ru
Ich bin mir nicht sicher, ob ich verstehe, was du tust - würdest du nicht erwarten, dass es die gleiche Größe zurückgibt, da du es mit der gleichen Zeichenfolge "Test" ausgibst, und es verwendet, um die Berechnung durchzuführen?
hinzugefügt der Autor rdelmar, Quelle
Entschuldigung, ich meine, dass es die gleiche Größe zurückgibt, egal welche Zeichenfolge ich gebe. Wenn ich eine längere Zeichenfolge zuordne, kann ich sehen, dass das Textfeld korrekt skaliert wird, damit es in die Zeichenfolge passt, aber die "fittingSize" -Methode der Zelle gibt immer noch dieselbe Höhe zurück.
hinzugefügt der Autor Jacopo, Quelle

2 Antworten

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!

Also, wie das zu beheben? Nun, Sie haben ein Textfeld, und Sie geben ihm Inhalt, und Sie möchten seine Höhe wissen. Wenn das Textfeld jedoch umbrochen wird, hängt die Höhe von der Breite ab: Sie wird schmaler und das Textfeld wird in mehr Zeilen umgebrochen, sodass es mehr Höhe verbraucht. Um also die bevorzugte Höhe für ein umschließendes Textfeld zu messen, müssen Sie ihm die Breite angeben, um die es gewickelt werden soll.

Unter OS X Mountain Lion und iOS 6 können Sie dies mit der Methode [NSTextField setPreferredMaxLayoutWidth:] tun. Wenn Sie beispielsweise die Höhe auf der Grundlage einer Breite von 100 berechnen möchten, rufen Sie [textField setPreferredMaxLayoutWidth: 100] ; Jetzt wird fittingSize eine Höhe für das Textfeld basierend auf dem Umbruch mit einer Breite von 100 angeben.

Das ist übrigens eine schlechte Idee:

[self removeConstraints:self.constraints];

Weil dadurch Einschränkungen beseitigt werden, die andere Teile des Systems hinzugefügt haben. Sie sollten eine Constraint, die Sie erstellt haben, nur entweder im Code oder in IB entfernen.

7
hinzugefügt
Danke für den Vorschlag, aber leider scheint es nicht zu funktionieren. Ich habe die Zeile entfernt, die alle Abhängigkeiten löscht, und hinzugefügt '[_dummyCell.expandingTextField setPreferredMaxLayoutWidth: 100.0];' zur Instanziierung von '_dummyCell'. Die Methode 'fittingSize' gibt immer den gleichen Wert zurück, unabhängig von der Länge der Zeichenfolge, die ich übergeben habe. Mein Problem scheint tiefer zu liegen. Ich kann Log-Ausgaben und Breakpoints in die Methoden 'fittingSize' und 'intrinsicContentSize' des Textfelds setzen und ich kann sehen, dass sie nie aufgerufen werden. Zur gleichen Zeit kann ich sehen, dass das Textfeld tatsächlich eine Unteransicht von '_dummyCell' ist
hinzugefügt der Autor Jacopo, Quelle
Ich kann das Problem leicht lösen, indem ich manuell die Methode 'intrinsicContentSize' jeder Teilansicht von '_dummyCell' aufruft und seine Höhe berechne, aber ich dachte, dass Einschränkungen das für mich tun sollten.
hinzugefügt der Autor Jacopo, Quelle
Nachdem ich ein bisschen mehr damit gespielt habe, habe ich herausgefunden, dass die Einstellung 'preferredMaxWidthLayout' des Textfelds nur für ein nicht editierbares Textfeld funktioniert. Bei einem editierbaren Textfeld wird die Eigenschaft einfach ignoriert.
hinzugefügt der Autor Jacopo, Quelle
Sehr wertvoller Punkt Jacopo. Vielen Dank. rettete mir viel Zeit
hinzugefügt der Autor jiminybob99, Quelle

Probieren Sie es aus (klicken Sie dazu auf den Hintergrund der XIB oder des Storyboards)

enter image description here

6
hinzugefügt
Ich kann das nicht tun. Die Methoden "fittingSize" und "intrinsicContentSize", die ich verwenden möchte, sind Teil des automatischen Layoutsystems. Die 'fittingSize'-Methode soll die Einschränkungen berücksichtigen.
hinzugefügt der Autor Jacopo, Quelle
Oh. Sie können mir nicht helfen. Es tut uns leid
hinzugefügt der Autor OnkaPlonka, Quelle