Pregunta

Tengo un NSTextFieldCell que quiero mostrar con alineación vertical medio. Gracias a una pregunta más vieja aquí y una entrada de blog que tiene dos soluciones de trabajo.

Sin embargo, ambas soluciones parecen aplastar mi capacidad de fijar la célula como alineado a la derecha. ¿Puede alguien ayudarme a hacer cualquiera de estas soluciones de apoyo a ambas formas de alineación?

Aquí está el código para una solución:

@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 solución alternativa es (obtenido de este el 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
¿Fue útil?

Solución

Quiero poner esta respuesta a la pregunta ya que el trabajo, sin embargo, creo que el hecho de que no podía encontrar otra manera de comprobar el ajuste de la alineación del IB es muy molesto. Acceso a _cFlags sólo parece un poco sucio, y me encantaría encontrar un método más limpio.

Con base en el código publicado a principios de este entrada de blog.

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

Otros consejos

Puede utilizar NSParagraphStyle / NSMutableParagraphStyle para establecer la alineación (y otros atributos). Añadir un objeto NSParagraphStyle configurado apropiadamente a la gama completa de su cadena con atributos.

Hay un par de soluciones potenciales publicados en un pregunta similar que pedí hace un tiempo.

En honor a la verdad, todavía utilizo el booleano _cFlags.vCentered indocumentado ( tsk tsk , mal programador!) Para hacer el trabajo. Es muy sencillo, y funciona. Voy a reinventar la rueda más adelante si tengo que hacerlo.

actualización:

OK, creo que he descubierto. Ambas soluciones se basan en una llamada a super para obtener el rect por defecto, y luego modificar origin.y y size.height para realizar el centrado vertical. Las llamadas a super, sin embargo, devolver un rectángulo cuya anchura ya se ha ajustado para ajustar el texto horizontalmente.

La solución es utilizar origin.x y size.width de los límites rect que se pasa en el método:

  

En la solución # 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;
}
  

En la solución # 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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top