0

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

1)有没有更好的方法来产生压缩字体行间距?2)或者你将如何向下移动文本渲染使其不会被剪裁。

<更新>

好的,我在下面的回答确实解决了使用 NSTextField 时的解决方案。但这显然也不适用于 NSTextView。我厌倦了重写 NSLayoutManagerDelegate 的 shouldSetLineFragmentRect... 方法中的 baselineOffset,但它也忽略了基线调整。使用 NSTextView 时有人有什么建议吗?

</更新>

谢谢!

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

使用剪裁的顶部文本进行渲染

代码:

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;
4

1 回答 1

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

在此处输入图像描述

于 2018-01-31T20:43:31.950 回答