NSTextFieldCell alineación vertical, las soluciones parecen aplastar la alineación horizontal
-
20-09-2019 - |
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
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;
}