NSTextField с сокращенным межстрочным интервалом…
Я пытаюсь понять, как правильно отображать текст с сокращенным межстрочным интервалом в текстовом поле. Когда я устанавливаю свойства стиля абзаца lineHeightMultiple, MaximumLineHeight и imumLineHeight, я могу добиться эффекта уплотнения линий, но одним побочным эффектом является то, что верхняя строка текста просто обрезается. Поэтому я подумал, что смогу просто переместить текст вниз с помощью NSBaselineOffsetAttributeName (используя отрицательное значение), но это, похоже, не имеет никакого эффекта. Я использую здесь высоту строки, равную 70% размера точки, но отсечение становится тем хуже, чем более сжатым.
1) Есть ли лучший способ получить сокращенный интервал между шрифтами? 2) Или, как бы вы переместили текстовый рендеринг вниз, чтобы он не обрезался.
<обновление>
Хорошо, мой ответ ниже касается решения при использовании NSTextField's. Но это, очевидно, не работает и для NSTextView. Я устал переопределять baselineOffset в методе mustSetLineFragmentRect... NSLayoutManagerDelegate, но он также игнорирует корректировки базовой линии. У кого-нибудь есть предложения при работе с NSTextView?
обновление>
Спасибо!
Вот тестовый проект, с которым я работаю https://www.dropbox.com/s/jyshqeuirujf71g/WhatThe.zip?dl=0
Codez:
self.label.wantsLayer = YES;
self.label.backgroundColor = [NSColor whiteColor];
self.label.hidden = NO;
self.label.maximumNumberOfLines = 0;
NSMutableDictionary *result = [NSMutableDictionary dictionary];
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
NSFont *font = [NSFont systemFontOfSize:80.0f];
CGFloat lineHeight = font.pointSize * .7f;
CGFloat natualLineHeight = font.ascender + ABS(font.descender) + font.leading;
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
paragraphStyle.alignment = NSTextAlignmentLeft;
paragraphStyle.lineHeightMultiple = lineHeight / natualLineHeight;
paragraphStyle.maximumLineHeight = lineHeight;
paragraphStyle.minimumLineHeight = lineHeight;
paragraphStyle.paragraphSpacing = 0.0f;
paragraphStyle.allowsDefaultTighteningForTruncation = paragraphStyle.lineBreakMode != NSLineBreakByWordWrapping && paragraphStyle.lineBreakMode != NSLineBreakByCharWrapping && paragraphStyle.lineBreakMode != NSLineBreakByClipping;
result[NSParagraphStyleAttributeName] = paragraphStyle;
result[NSKernAttributeName] = @(0.0f);
result[NSBaselineOffsetAttributeName] = @(-50.0f);
result[NSFontAttributeName] = font;
result[NSForegroundColorAttributeName] = [NSColor blackColor];
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:@"Hello\nThere" attributes:result];
self.label.attributedStringValue = attributedString;
1 ответ
Хорошо. Подклассом NSTextFieldCell я смог корректно сместить текст. Обидно, что этот метод прекрасно работает в iOS-стране. Возможно, это сработает, когда этим летом будут выпущены унифицированные интерфейсы API для Mac / iOS.
Это удалит все отрицательные значения базовой линии из строки перед ее прорисовкой и прорисовкой внутри смещенного прямоугольника.
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
NSRect titleRect = [self titleRectForBounds:cellFrame];
NSMutableAttributedString *string = [self.attributedStringValue mutableCopy];
__block CGFloat baselineOffset = 0.0f;
[string enumerateAttributesInRange:NSMakeRange(0, string.length) options:0 usingBlock:^(NSDictionary<NSAttributedStringKey,id> * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) {
NSNumber *offsetValue = attrs[NSBaselineOffsetAttributeName];
if (offsetValue != nil && offsetValue.floatValue < 0.0f) {
baselineOffset = MIN(baselineOffset, offsetValue.floatValue);
[string removeAttribute:NSBaselineOffsetAttributeName range:range];
}
}];
titleRect.origin.y -= baselineOffset;
[string drawInRect:titleRect];
}