Domanda

Ho un NSTableView con diverse colonne di testo. Per impostazione predefinita, il dataCell per queste colonne è un'istanza della classe NSTextFieldCell di Apple, che fa tutti i tipi di cose meravigliose, ma disegna il testo allineato con la parte superiore della cella, e voglio che il testo sia centrato verticalmente nella cella.

C'è un flag interno in NSTextFieldCell che può essere usato per centrare verticalmente il testo e funziona magnificamente. Tuttavia, poiché è una bandiera interna, il suo utilizzo non è sanzionato da Apple e potrebbe semplicemente scomparire senza preavviso in una versione futura. Attualmente sto usando questo flag interno perché è semplice ed efficace. Apple ha ovviamente impiegato del tempo per implementare la funzionalità, quindi non mi piace l'idea di implementarla di nuovo.

; la mia domanda è questa: Qual è il modo giusto per implementare qualcosa che si comporta esattamente come NStextFieldCell di Apple, ma disegna un testo centrato verticalmente anziché allineato in alto?

Per la cronaca, ecco la mia attuale "soluzione":

@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

Usato come segue:

[[myTableColumn dataCell] setVerticalCentering:YES];
È stato utile?

Soluzione

Le altre risposte non hanno funzionato per più righe. Pertanto, inizialmente ho continuato a utilizzare la proprietà cFlags.vCentered non documentata, ma ciò ha causato il rifiuto della mia app dall'app store. Ho finito per usare una versione modificata della soluzione di Matt Bell che funziona per più righe, a capo automatico e un'ultima linea troncata:

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

(Questo codice presuppone ARC; aggiungere un rilascio automatico dopo attrString.mutableCopy se si utilizza la gestione manuale della memoria)

Altri suggerimenti

Sostituire -titleRectForBounds di NSCell: dovrebbe farlo - questo è il metodo responsabile per dire alla cella dove disegnare il suo testo:

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

Cordiali saluti, questo funziona bene, anche se non sono riuscito a mantenerlo centrato quando modifichi la cella ... A volte ho celle con grandi quantità di testo e questo codice può causare disallineamenti se il testo l'altezza è maggiore della cella in cui sta cercando di centrarla verticalmente. Ecco il mio metodo modificato:

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

Per chiunque stia tentando questo usando il metodo drawInteriorWithFrame: inView: di Matt Ball, questo non disegnerà più uno sfondo se hai impostato la cella per disegnarne uno. Per risolvere questo, aggiungi qualcosa sulla falsariga di

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

all'inizio del metodo drawInteriorWithFrame: inView: .

Anche se questa è una domanda piuttosto vecchia ...

Credo che lo stile predefinito dell'implementazione di NSTableView sia inteso esclusivamente per la visualizzazione di testo a riga singola con tutte le stesse dimensioni e amp; font.

In tal caso, mi raccomando,

  1. Imposta carattere.
  2. Regola rowHeight .

Forse otterrai file abbastanza dense. E poi, dai loro il riempimento impostando intercellSpacing .

Ad esempio,

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

Ecco cosa otterrai con due aggiustamenti di proprietà.

inserisci qui la descrizione dell'immagine

Questo non funzionerà per il testo su più righe, ma abbastanza buono per un centro verticale rapido se non hai bisogno del supporto per più righe.

Ho avuto lo stesso problema ed ecco la soluzione che ho fatto:

1) In Interface Builder, seleziona NSTableCellView. Assicurati che sia grande quanto l'altezza della riga in Impostazioni dimensioni. Ad esempio, se l'altezza della riga è 32, imposta l'altezza della cella 32

2) Assicurati che la tua cella sia ben posizionata nella riga (intendo visibile)

3) Seleziona il tuo TextField all'interno del tuo cellulare e vai al tuo ispettore delle dimensioni

4) Dovresti vedere " Organizza " elemento e seleziona " Centra verticalmente nel contenitore "

- > TextField si centrerà nella cella

No. Il modo giusto è mettere il campo in un'altra vista e utilizzare il layout automatico o il layout di quella vista padre per posizionarlo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top