Czy istnieje "właściwy" sposób, aby nstextfieldcell narysował pionowo wyśrodkowany tekst?

Mam NSTableView z kilkoma kolumnami tekstowymi. Domyślnie dataCell dla tych kolumn jest instancją klasy Apple NSTextFieldCell, która robi wiele wspaniałych rzeczy, ale rysuje tekst wyrównany do górnej części komórki i chcę, aby tekst był wyśrodkowany pionowo w komórce.

W NSTextFieldCell znajduje się wewnętrzna flaga, która może być używana do wyśrodkowania tekstu w pionie i działa pięknie. Ponieważ jednak jest to flaga wewnętrzna, jej użycie nie jest usankcjonowane przez Apple i może po prostu znikają bez ostrzeżenia w przyszłym wydaniu. Obecnie używam tej wewnętrznej flagi, ponieważ jest prosta i skuteczna. Apple najwyraźniej poświęciło trochę czasu na implementację tej funkcji, więc nie podoba mi się pomysł jej ponownego wdrożenia.

Więc; moje pytanie jest takie: jaki jest właściwy sposób, aby zaimplementować coś, co zachowuje się dokładnie jak Nstextfieldcell Apple, ale rysuje wyśrodkowany pionowo tekst zamiast wyrównany do góry?

Dla przypomnienia, oto mój obecny "rozwiązanie": {]}

@interface NSTextFieldCell (MyCategories)
- (void)setVerticalCentering:(BOOL)centerVertical;
@end

@implementation NSTextFieldCell (MyCategories)
- (void)setVerticalCentering:(BOOL)centerVertical
{
    @try { _cFlags.vCentered = centerVertical ? 1 : 0; }
    @catch(...) { NSLog(@"*** unable to set vertical centering"); }
}
@end

Używane w następujący sposób:

[[myTableColumn dataCell] setVerticalCentering:YES];
Author: e.James, 2009-08-05

7 answers

Inne odpowiedzi nie działały dla wielu linii. Dlatego początkowo nadal używałem nieudokumentowanej właściwości cFlags.vCentered, ale to spowodowało, że moja aplikacja została odrzucona ze sklepu z aplikacjami. Ostatecznie użyłem zmodyfikowanej wersji Rozwiązania Matta Bella, która działa dla wielu linii, zawijania słów i skróconej ostatniej linii: {]}

-(void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
    NSAttributedString *attrString = self.attributedStringValue;

    /* if your values can be attributed strings, make them white when selected */
    if (self.isHighlighted && self.backgroundStyle==NSBackgroundStyleDark) {
        NSMutableAttributedString *whiteString = attrString.mutableCopy;
        [whiteString addAttribute: NSForegroundColorAttributeName
                            value: [NSColor whiteColor]
                            range: NSMakeRange(0, whiteString.length) ];
        attrString = whiteString;
    }

    [attrString drawWithRect: [self titleRectForBounds:cellFrame] 
                     options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin];
}

- (NSRect)titleRectForBounds:(NSRect)theRect {
    /* get the standard text content rectangle */
    NSRect titleFrame = [super titleRectForBounds:theRect];

    /* find out how big the rendered text will be */
    NSAttributedString *attrString = self.attributedStringValue;
    NSRect textRect = [attrString boundingRectWithSize: titleFrame.size
                                               options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin ];

    /* If the height of the rendered text is less then the available height,
     * we modify the titleRect to center the text vertically */
    if (textRect.size.height < titleFrame.size.height) {
        titleFrame.origin.y = theRect.origin.y + (theRect.size.height - textRect.size.height) / 2.0;
        titleFrame.size.height = textRect.size.height;
    }
    return titleFrame;
}

(ten kod zakłada ARC; dodaj autorelease po attrstringu.mutableCopy jeśli używasz ręcznego zarządzania pamięcią)

 35
Author: Jakob Egger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-03 08:44:45

Nadpisanie -titleRectForBounds: NSCell powinno to zrobić -- to metoda odpowiedzialna za wskazanie komórce, gdzie ma narysować swój tekst:

- (NSRect)titleRectForBounds:(NSRect)theRect {
    NSRect titleFrame = [super titleRectForBounds:theRect];
    NSSize titleSize = [[self attributedStringValue] size];
    titleFrame.origin.y = theRect.origin.y + (theRect.size.height - titleSize.height) / 2.0;
    return titleFrame;
}

- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
    NSRect titleRect = [self titleRectForBounds:cellFrame];
    [[self attributedStringValue] drawInRect:titleRect];
}
 30
Author: Matt Ball,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-06 10:11:15

Dla twojej wiadomości, to działa dobrze, chociaż nie udało mi się go wyśrodkować, kiedy edytujesz komórkę... Czasami mam komórki z dużą ilością tekstu i ten kod może spowodować, że zostaną one błędnie dopasowane, jeśli wysokość tekstu jest większa niż komórka, w której próbuje wyśrodkować go pionowo. Oto moja zmodyfikowana metoda:

- (NSRect)titleRectForBounds:(NSRect)theRect 
 {
    NSRect titleFrame = [super titleRectForBounds:theRect];
    NSSize titleSize = [[self attributedStringValue] size];
     // test to see if the text height is bigger then the cell, if it is,
     // don't try to center it or it will be pushed up out of the cell!
     if ( titleSize.height < theRect.size.height ) {
         titleFrame.origin.y = theRect.origin.y + (theRect.size.height - titleSize.height) / 2.0;
     }
    return titleFrame;
}
 4
Author: e.James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-17 01:59:47

Dla każdego, kto spróbuje tego użyć metody drawInteriorWithFrame:inView: Matta Balla, nie będzie już rysować tła, jeśli Ustawiłeś komórkę, aby ją narysować. Aby rozwiązać ten problem dodaj coś w stylu

[[NSColor lightGrayColor] set];
NSRectFill(cellFrame);

Do początku twojej metody drawInteriorWithFrame:inView:.

 4
Author: Greg Sexton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-02 22:19:09

Chociaż to dość stare pytanie...

Uważam, że domyślny styl implementacji nstableview jest przeznaczony wyłącznie do wyświetlania tekstu w jednej linii z taką samą czcionką i rozmiarem.

W takim razie polecam,

  1. Ustaw czcionkę.
  2. Dopasuj rowHeight.

Może będziesz cicho gęste rzędy. A następnie, dać im padding przez ustawienie intercellSpacing.

Na przykład,

    core_table_view.rowHeight               =   [NSFont systemFontSizeForControlSize:(NSSmallControlSize)] + 4;
    core_table_view.intercellSpacing        =   CGSizeMake(10, 80);

Oto co dostaniesz z dwóch nieruchomości / align = "left" /

Tutaj wpisz opis obrazka

To nie będzie działać dla tekstu wielowierszowego, ale wystarczająco dobre dla szybkiego centrum pionowego, jeśli nie potrzebujesz obsługi wielowierszowej.

 2
Author: Eonil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-19 21:48:22

Miałem ten sam problem i oto rozwiązanie, które zrobiłem:

1) w Interface Builder wybierz NSTableCellView. Upewnij się, że jest tak duży, jak wysokość rzędu w Inspektorze rozmiaru. Na przykład, jeśli wysokość wiersza wynosi 32, Ustaw wysokość komórki na 32

2) Upewnij się, że komórka jest dobrze umieszczona w rzędzie (mam na myśli widoczne)

3) Wybierz pole tekstowe w komórce i przejdź do inspektora rozmiaru

4) Powinieneś zobaczyć" ułóż "element i wybrać" środek pionowo w Container "

-- > pole tekstowe wyśrodkuje się w komórce

 1
Author: AllezLesBleus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-10 15:09:38

Nie. Dobrym sposobem jest umieszczenie pola w innym widoku i użycie układu auto lub układu widoku nadrzędnego do jego pozycjonowania.

 0
Author: Frank Krueger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-22 15:59:26