2009-11-18 12 views
9

Ho un NSTextFieldCell che desidero visualizzare con allineamento centrale verticale. Grazie ad una vecchia domanda qui e un post sul blog ho due soluzioni funzionanti.Allineamento verticale NSTextFieldCell, le soluzioni sembrano schiacciare l'allineamento orizzontale

Tuttavia, entrambe le soluzioni sembrano schiacciare la mia capacità di impostare la cella come allineata a destra. Qualcuno può aiutarmi a fare in modo che una di queste soluzioni supporti entrambe le forme di allineamento?

Ecco il codice per una soluzione:

@implementation MiddleAlignedTextFieldCell 

- (NSRect)titleRectForBounds:(NSRect)theRect { 
    NSRect titleFrame = [super titleRectForBounds:theRect]; 
    NSSize titleSize = [[self attributedStringValue] size]; 
    titleFrame.origin.y = theRect.origin.y - .5 + (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]; 
} 

@end 

La soluzione alternativa è (ottenuto da this blog):

@implementation RSVerticallyCenteredTextFieldCell 

- (NSRect)drawingRectForBounds:(NSRect)theRect 
{ 
    NSRect newRect = [super drawingRectForBounds:theRect]; 

    if (mIsEditingOrSelecting == NO) 
    { 
     // Get our ideal size for current text 
     NSSize textSize = [self cellSizeForBounds:theRect]; 

     // Center that in the proposed rect 
     float heightDelta = newRect.size.height - textSize.height; 
     if (heightDelta > 0) 
     { 
      newRect.size.height -= heightDelta; 
      newRect.origin.y += (heightDelta/2); 
     } 
    } 

    return newRect; 
} 

- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(int)selStart length:(int)selLength 
{ 
    aRect = [self drawingRectForBounds:aRect]; 
    mIsEditingOrSelecting = YES;  
    [super selectWithFrame:aRect inView:controlView editor:textObj delegate:anObject start:selStart length:selLength]; 
    mIsEditingOrSelecting = NO; 
} 

- (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject event:(NSEvent *)theEvent 
{ 
    aRect = [self drawingRectForBounds:aRect]; 
    mIsEditingOrSelecting = YES; 
    [super editWithFrame:aRect inView:controlView editor:textObj delegate:anObject event:theEvent]; 
    mIsEditingOrSelecting = NO; 
} 

@end 

risposta

5

Sto postando questa risposta alla domanda poiché funziona, tuttavia, trovo il fatto che non sono riuscito a trovare un altro modo per controllare l'impostazione di allineamento da IB è molto fastidioso. L'accesso a _cFlags sembra un po 'sporco, e mi piacerebbe trovare un metodo più pulito.

In base al codice pubblicato in precedenza da this blog entry.

- (NSRect)drawingRectForBounds:(NSRect)theRect 
{ 
    // Get the parent's idea of where we should draw 
    NSRect newRect = [super drawingRectForBounds:theRect]; 

    if (mIsEditingOrSelecting == NO) 
    { 
     // Get our ideal size for current text 
     NSSize textSize = [self cellSizeForBounds:theRect]; 

     // Center that in the proposed rect 
     float heightDelta = newRect.size.height - textSize.height; 
     if (heightDelta > 0) 
     { 
      newRect.size.height -= heightDelta; 
      newRect.origin.y += (heightDelta/2); 
     } 

     // For some reason right aligned text doesn't work. This section makes it work if set in IB. 
     // HACK: using _cFlags isn't a great idea, but I couldn't find another way to find the alignment. 
     // TODO: replace _cFlags usage if a better solution is found. 
     float widthDelta = newRect.size.width - textSize.width; 
     if (_cFlags.alignment == NSRightTextAlignment && widthDelta > 0) { 
      newRect.size.width -= widthDelta; 
      newRect.origin.x += widthDelta; 
     } 

    } 

    return newRect; 
} 
3

È possibile utilizzare NSParagraphStyle/NSMutableParagraphStyle per impostare l'allineamento (e altri attributi). Aggiungi un oggetto NSParagraphStyle opportunamente configurato all'intero intervallo della stringa attribuita.

+0

Questo mi richiede di accoppiare quella parte della presentazione con il mio livello dati, e onestamente non sono sicuro che mi piaccia. Questo dovrebbe rispettare le opzioni presentate in IB, ma per alcuni motivi non lo è (per quanto riguarda l'allineamento verticale dovrebbe essere un'opzione in IB). –

+0

Non sono sicuro di come lo si mischia più che impostare la stringa di NSTextFieldCell su qualcosa dal livello del modello.:-) L'allineamento (e il carattere, il colore e la dimensione, ...) fa parte di tutto questo. Sono d'accordo, tuttavia, che l'allineamento verticale dovrebbe essere un'opzione: file un rapporto di miglioramento. Dal momento che non è disponibile, dovrai tenerne conto nel codice del disegno. –

+0

Er, questa è "richiesta di miglioramento". Link: http://bugreporter.apple.com –

2

Ci sono un paio di soluzioni potenziali pubblicate in un similar question che ho chiesto un po 'di tempo fa.

In tutta onestà, ho ancora utilizzare il non documentato _cFlags.vCentered booleana (tsk tsk, programmatore male!) Per ottenere il lavoro fatto. È semplice e funziona. Reinventerò la ruota in seguito, se necessario.

aggiornamento:

OK, credo di aver capito. Entrambe le soluzioni si basano su una chiamata a super per ottenere il valore predefinito, quindi modificare origin.y e size.height per eseguire il centraggio verticale. Le chiamate a super, tuttavia, restituiscono un rettangolo la cui larghezza è già stata adattata per adattarsi al testo in senso orizzontale.

La soluzione è quella di utilizzare origin.x e size.width dai legami rect che viene passato al metodo:

in soluzione # 1:

- (NSRect)titleRectForBounds:(NSRect)theRect { 
    NSRect titleFrame = [super titleRectForBounds:theRect]; 
    NSSize titleSize = [[self attributedStringValue] size]; 

    // modified: 
    theRect.origin.y += (theRect.size.height - titleSize.height)/2.0 - 0.5; 
    return theRect; 
} 

In soluzione # 2 :

- (NSRect)drawingRectForBounds:(NSRect)theRect 
{ 
    NSRect newRect = [super drawingRectForBounds:theRect]; 

    // modified: 
    newRect.origin.x = theRect.origin.x; 
    newRect.size.width = theRect.size.width; 

    if (mIsEditingOrSelecting == NO) 
    { 
     // Get our ideal size for current text 
     NSSize textSize = [self cellSizeForBounds:theRect]; 

     // Center that in the proposed rect 
     float heightDelta = newRect.size.height - textSize.height; 
     if (heightDelta > 0) 
     { 
      newRect.size.height -= heightDelta; 
      newRect.origin.y += (heightDelta/2); 
     } 
    } 

    return newRect; 
} 
+0

In realtà era la soluzione a questa domanda che ho trovato una delle mie soluzioni. –

+0

Sto solo cercando di capire come mantenere l'allineamento orizzontale con questa soluzione. Ma potrei dover scendere e provare un'altra via se non posso. –

+0

Sono sorpreso che l'allineamento orizzontale sia influenzato da nessuna di queste soluzioni, dal momento che nessuno dei due ha problemi con la dimensione x. Come stai impostando l'allineamento? –

Problemi correlati