Pytanie Jak pozwolić NSTextField rosnąć z tekstem w układzie automatycznym?


Automatyczny układ w Lionu powinien sprawić, że pole tekstowe (a tym samym etykieta) będzie rosło wraz z tekstem.

Pole tekstowe ustawiane jest w programie Interface Builder.

Jaki jest prosty i niezawodny sposób na zrobienie tego?


33
2018-05-05 16:15


pochodzenie




Odpowiedzi:


Metoda intrinsicContentSize w NSView zwraca to, co sam pogląd uważa za swój wewnętrzny rozmiar treści.

NSTextField oblicza to bez uwzględnienia wraps właściwość jego komórki, więc zgłasza wymiary tekstu, jeśli są ułożone w jednej linii.

Stąd niestandardowa podklasa NSTextField może zastąpić tę metodę, aby zwrócić lepszą wartość, taką jak ta dostarczona przez komórkę cellSizeForBounds: metoda:

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

43
2018-05-05 16:28



To dokładnie pasuje do tego, co widzę. Dla wyjaśnienia, ignorowanie własności "okładów" w komórce wydaje się być błędem w Lionie, który został naprawiony w Mountain Lion. Tak więc, jeśli celujesz w Lwa i powyżej, zobaczysz różne wyniki w 2 systemach operacyjnych, dopóki nie zastosujesz poprawki błędów, aby przyspieszyć działanie Lwa. - Scott Roth
Tak, to błąd w Lion. Naprawdę chciałbym, aby Apple naprawił te problemy zarówno w OS X 10.7 i 10.8. W mojej implementacji robię jeszcze więcej kontroli dla przypadków specjalnych (np. Jeśli to Lion || Jeśli językiem nie jest angielski) i ustawiam swój wzrost trochę inaczej. Niemniej jednak to, co napisał Monolo, to dobry początek. - Arvin
Metoda intrinsicContentSize: nie jest wywoływana, gdy zmienisz tekst w niej za pomocą metody setStringValue :. - ideawu
musisz unieważnić układ w - (void) textDidChange: (NSNotification *) notification {[super textDidChange: notification]; [self invalidateIntrinsicContentSize]; } - Peter Lapisu
Czy ktokolwiek ostatnio zrobił wersję Swift? - Clifton Labrum


Swift 4

Edytowalna autosynkcja NSTextField

Oparty na poście Objective-C Petera Lapisu

Podklasa NSTextField, dodaj poniższy kod.

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

Oprawa self.frame.size.height do "rozsądnej liczby" unika niektóre błędy podczas korzystania FLT_MAX, CGFloat.greatestFiniteMagnitude lub duże liczby. Błędy pojawiają się podczas pracy, gdy użytkownik wybierze podświetlony tekst w polu, mogą przeciągnąć w górę iw dół w nieskończoność. Dodatkowo, gdy użytkownik wprowadza tekst NSTextField jest wygaszony, dopóki użytkownik nie zakończy edycji. Wreszcie, jeśli użytkownik wybrał opcję NSTextField a następnie próbuje zmienić rozmiar okna, jeśli wartość wynosi self.frame.size.height jest za duże, okno się zawiesi.


2
2018-03-23 13:40





Przyjęta odpowiedź opiera się na manipulowaniu intrinsicContentSize ale to może nie być konieczne we wszystkich przypadkach. Autolayout będzie rosnąć i zmniejszać wysokość pola tekstowego, jeśli (a) podasz pole tekstowe a preferredMaxLayoutWidth i (b) uczynić pole nie editable. Te kroki umożliwiają polu tekstowemu określenie jego wewnętrznej szerokości i obliczenie wysokości wymaganej dla autolayout. Widzieć ta odpowiedź i ta odpowiedź po więcej szczegółów.

Jeszcze bardziej niejasno wynika to z zależności od pola tekstowego editable atrybut, że autolayout ulegnie zerwaniu, jeśli używasz powiązań na tym polu i nie wyczyścisz go Conditionally Sets Editable opcja.


0
2017-12-08 03:08