Pergunta

Eu tenho um NSTableView com várias colunas de texto. Por padrão, o dataCell para estas colunas é uma instância da classe NSTextFieldCell da Apple, que faz todos os tipos de coisas maravilhosas, mas ele desenha texto alinhado com a parte superior da célula, e eu quero o texto a ser centralizado verticalmente na célula.

Há um sinalizador interno no NSTextFieldCell que pode ser usado para centralizar verticalmente o texto, e ele funciona muito bem. No entanto, uma vez que é um sinalizador interno, o seu uso não é sancionado pela Apple e que poderia simplesmente desaparecer sem aviso em uma versão futura. Atualmente, estou usando esta bandeira interna, porque é simples e eficaz. A Apple tem, obviamente, passou algum tempo implementar o recurso, por isso eu não gosto da idéia de re implementando-lo.

Assim; minha pergunta é esta:? O que é a maneira correta de implementar algo que se comporta exatamente como NStextFieldCell da Apple, mas chama verticalmente centralizado texto em vez de alinhados-top

Para o registro, aqui está a minha "solução" atual:

@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

Usado como segue:

[[myTableColumn dataCell] setVerticalCentering:YES];
Foi útil?

Solução

As outras respostas não funcionou para várias linhas. Portanto, eu inicialmente continuou usando a propriedade cFlags.vCentered situação irregular, mas que causou meu aplicativo para ser rejeitado na App Store. Acabei usando uma versão modificada da solução de Matt Bell que funciona para várias linhas, quebra de linha, e uma última linha truncado:

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

(Este código assume ARC, adicione um disparo automático após attrString.mutableCopy se você usar o gerenciamento de memória manual)

Outras dicas

-titleRectForBounds: de Overriding NSCell deve fazê-lo - que é o método responsável por dizer a célula onde desenhar seu texto:

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

FYI, isso funciona bem, embora eu não conseguiram obtê-lo a permanecer centrado quando você editar a célula ... Eu às vezes têm células com grandes quantidades de texto e este código pode resultar em eles serem desalinhados Se o texto a altura é maior, então a célula que está tentando verticalmente centralizá-lo em Aqui é o meu método modificado:.

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

Para qualquer um de tentar esta usando o método drawInteriorWithFrame:inView: de Matt Bola, isso não vai mais chamar um fundo se você tiver definido o seu celular para desenhar um. Para resolver esse acrescentar algo ao longo das linhas

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

para o início de seu método drawInteriorWithFrame:inView:.

Embora isso é muito velha pergunta ...

Eu acredito estilo padrão de implementação NSTableView se destina estritamente para exibição de texto única linha com todos mesmo tamanho e tipo de letra.

Nesse caso, eu recomendo,

  1. fonte definido.
  2. Ajustar rowHeight.

Talvez você terá linhas tranquilamente densas. E, em seguida, dar-lhes cobertura, definindo intercellSpacing.

Por exemplo,

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

Aqui o que você vai ter com ajuste de duas propriedades.

enter descrição da imagem aqui

Isso não vai funcionar para o texto multi-linha, mas muito bom o suficiente para centro vertical rápido se você não precisa de suporte a multi-line.

Eu tive o mesmo problema e aqui está a solução que eu fiz:

1) Em Interface Builder, selecione o NSTableCellView. Certifique-se que tão grande quanto a altura da linha no tamanho Inspector. Por exemplo, se a sua altura da linha é de 32, faça seu celular altura 32

2) Verifique se o seu celular está bem colocado na sua fila (I média visível)

3) Selecione seu TextField dentro do seu celular e vá para seu inspector tamanho

4) Você deve ver "Organizar" item e selecione "Centralizar verticalmente em Container"

-> O TextField vai centrar-se na célula

No. O caminho certo é colocar o campo em outro esquema auto vista e uso ou disposição que da vista pai para posicioná-lo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top