带有压缩字体行间距的NSTextField ...

时间:2018-01-31 13:20:28

标签: cocoa nstextfield appkit nstextview nsparagraphstyle

我试图了解如何在文本字段中正确显示带有压缩行间距的文本。当我设置段落样式属性lineHeightMultiple,maximumLineHeight和minimumLineHeight时,我可以达到缩小线条的效果,但是一个副作用是文本的顶行被剪掉了。所以我认为我能够使用NSBaselineOffsetAttributeName(使用负值)向下移动文本,但这似乎没有任何效果。我在这里使用的线高是点大小的70%,但是剪切得越多,它就越精确。

1)是否有更好的方法来生成精简字体行间距? 2)或者如何向下移动文本渲染以使其不被剪裁。

<更新>

好的,我的答案确实解决了使用NSTextField时的解决方案。但这显然对NSTextView也不起作用。我厌倦了覆盖NSLayoutManagerDelegate的shouldSetLineFragmentRect ...方法中的baselineOffset,但它也忽略了基线调整。使用NSTextView时,任何人都有任何建议吗?

< /更新>

谢谢!

这是我正在使用https://www.dropbox.com/s/jyshqeuirujf71g/WhatThe.zip?dl=0

的测试项目

rendering with clipped top text

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 个答案:

答案 0 :(得分:0)

确定。通过子类化NSTextFieldCell,我能够正确地偏移文本。遗憾的是,这种方法在iOS版本中运行良好。也许这将在今年夏天发布统一的Mac / iOS UI API时起作用。

这将从字符串中删除任何负基线值,然后在移动的矩形内绘制和绘制。

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

enter image description here