NSTextFieldCell вертикальное выравнивание, решения, кажется, подавляют горизонтальное выравнивание
У меня есть NSTextFieldCell, который я хочу отображать со средним вертикальным выравниванием. Благодаря более старому вопросу и записи в блоге у меня есть два рабочих решения.
Тем не менее, оба решения, похоже, ограничивают мою способность устанавливать ячейку в правильное положение. Может ли кто-нибудь помочь мне заставить одно из этих решений поддерживать обе формы выравнивания?
Вот код для одного решения:
@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
Альтернативное решение (получено из этого блога):
@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
3 ответа
Я отправляю этот ответ на вопрос, поскольку он работает, однако я нахожу тот факт, что я не могу найти другой способ проверить настройку выравнивания в IB, очень раздражает. Доступ к _cFlags кажется немного грязным, и я бы хотел найти более чистый метод.
На основе кода, размещенного ранее в этой записи блога.
- (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;
}
Вы можете использовать NSParagraphStyle/NSMutableParagraphStyle, чтобы установить выравнивание (и другие атрибуты). Добавьте соответствующим образом настроенный объект NSParagraphStyle ко всему диапазону вашей приписанной строки.
Есть пара потенциальных решений, опубликованных в аналогичном вопросе, который я задал некоторое время назад.
Честно говоря, я все еще использую недокументированные _cFlags.vCentered
логическое (тск тск, плохой программист!), чтобы сделать работу. Все просто и работает. Я изобрету колесо позже, если придется.
Обновить:
ОК, думаю, я понял это. Оба решения опираются на призыв super
чтобы получить прямоугольник по умолчанию, а затем изменить origin.y
а также size.height
выполнить вертикальное центрирование. Призывы к super
однако верните прямоугольник, ширина которого уже была отрегулирована так, чтобы текст располагался горизонтально.
Решение заключается в использовании origin.x
а также size.width
из прямоугольника границ, который передается методу:
В решении № 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;
}
В решении № 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;
}