【问题标题】:NSAttributedString highlight/background color shows between lines (ugly)NSAttributedString 高亮/背景颜色在行之间显示(丑陋)
【发布时间】:2013-09-27 03:43:55
【问题描述】:

我试图在 NSTextView 中很好地显示突出显示的段落。现在,我通过创建一个带有背景颜色的 NSAttributedString 来做到这一点。下面是一些简化的代码:

NSDictionary *attributes = @{NSBackgroundColorAttributeName:NSColor.greenColor};
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:@"Here is a single line of text with single spacing" attributes:attributes];

[textView.textStorage setAttributedString:attrString];

这种方法基本上是有效的,因为它会产生突出显示的文本。

不幸的是,当存在多行时,高亮除了行本身之外,还覆盖了行之间的垂直空间,从而导致丑陋。

有人知道在 Cocoa 中进行这种突出显示的方法吗?下图基本就是我要找的(忽略白框上的阴影):

我愿意使用 CoreText、html 或任何必要的东西来使事情看起来更好。

【问题讨论】:

  • 你有没有解决过这个问题,我遇到了完全相同的问题
  • 我并没有真正弄清楚这一点,但我确实弄清楚了如何至少将选择矩形围绕文本居中,这样它就不会全部位于上方或下方。它涉及计算[paragraphStyle setLineSpacing:xx] 和[paragraphStyle setLineHeightMultiple:xx] 以使它们相同。同样,这并不能解决实际问题,只是让它更容易忍受。

标签: macos cocoa core-text nstextview nsattributedstring


【解决方案1】:

您需要继承 NSLayoutManager 并覆盖:

- (void)fillBackgroundRectArray:(const CGRect *)rectArray
                      count:(NSUInteger)rectCount
          forCharacterRange:(NSRange)charRange
                      color:(UIColor *)color;

这是绘制背景颜色矩形的原始方法。

【讨论】:

  • 如何实现上述方法将取决于您的应用程序。但是,作为附加上下文,我使用 - (void)enumerateLineFragmentsForGlyphRange:(NSRange)glyphRange usingBlock:(void (^)(CGRect rect, CGRect usedRect, NSTextContainer *textContainer, NSRange glyphRange, BOOL *stop))block 创建了一个 CGRect 结构数组,该数组描述了字符字形使用的边界,并创建了与 rectArray 内容的交集以限制我的高光边界。
【解决方案2】:

试试这个:-

     -(IBAction)chooseOnlylines:(id)sender
{

 NSString *allTheText =[tv string];
    NSArray *lines = [allTheText componentsSeparatedByString:@"\n"];
    NSString *str=[[NSString alloc]init];
    NSMutableAttributedString *attr;
    BOOL isNext=YES;
    [tv setString:@""];
    for (str in lines)
    {
        attr=[[NSMutableAttributedString alloc]initWithString:str];
        if ([str length] > 0)
        {

        NSRange range=NSMakeRange(0, [str length]);
        [attr addAttribute:NSBackgroundColorAttributeName value:[NSColor greenColor] range:range];
        [tv .textStorage appendAttributedString:attr];
            isNext=YES;
        }
        else
        {
            NSString *str=@"\n";
            NSAttributedString *attr=[[NSAttributedString alloc]initWithString:str];
            [tv .textStorage appendAttributedString:attr];
            isNext=NO;
        }
        if (isNext==YES)
        {
            NSString *str=@"\n";
            NSAttributedString *attr=[[NSAttributedString alloc]initWithString:str];
            [tv .textStorage appendAttributedString:attr];

        }
     }
}

【讨论】:

  • 不幸的是,在这种情况下,行没有被 \n 字符分隔——这是一个段落,所以文本被自动换行。不过,感谢您的尝试。
  • 我已经修改了代码。请立即尝试,它也不会换行。
【解决方案3】:

当用户点击该段落时需要突出显示该段落。这就是我实现它的方式,不要与 高亮颜色 混淆,它是我为此目的创建的自定义 NSAttributedString 键。

extension NSAttributedString.Key {
    public static let highlightColor = NSAttributedString.Key.init("highlightColor")
}

class ReaderLayoutManager: NSLayoutManager {

    // MARK: - Draw Background
    override func drawBackground(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) {
        super.drawBackground(forGlyphRange: glyphsToShow, at: origin)
        self.enumerateLineFragments(forGlyphRange: glyphsToShow) { (_, usedRect, _, range, _) in
            guard let highlightColor = self.currentHighlightColor(range: range) else { return }
            guard let context = UIGraphicsGetCurrentContext() else { return }
            var lineRect = usedRect
            lineRect.origin.y += 10
            lineRect.size.height -= 2
            context.saveGState()
            let path = UIBezierPath(roundedRect: lineRect, cornerRadius: 2)
            highlightColor.setFill()
            path.fill()
            context.restoreGState()
        }
    }

    private func currentHighlightColor(range: NSRange) -> UIColor? {
        guard let textStorage = textStorage else { return nil }
        guard let highlightColor = textStorage.attributes(at: range.location, effectiveRange: nil)[.highlightColor] as? UIColor else { return nil }
        return highlightColor
    }
}

当用户点击它时,我设置范围的高亮颜色并重置 TextView。

attributedString.addAttributes([.highlightColor: theme.textUnderlineColor], range: range)

【讨论】:

    猜你喜欢
    • 2013-04-17
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多