如何在NSTextAttachment中设置模板化图像的颜色

Gha*_*ull 24 nsattributedstring nstextattachment ios

如何设置作为属性字符串附件的模板化图像的颜色?

背景:

我有一个UILabel,我将其attributionText设置为NSAttributedString.NSAttributedString包含带有小图像的NSTextAttachment.现在我想让我的图像颜色与文本颜色匹配,我无法弄清楚如何使它工作.

我通常希望通过将其渲染模式设置为UIImageRenderingModeAlwaysTemplate然后在包含UIView上设置tintColor来为图像着色.我试过在我的UILabel上设置tintColor但是没有效果.

这是我的代码.它在Ruby(RubyMotion)中,因此语法可能看起来有点滑稽,但它与Objective C 1:1映射.

attachment = NSTextAttachment.alloc.initWithData(nil, ofType: nil)
attachment.image = UIImage.imageNamed(icon_name).imageWithRenderingMode(UIImageRenderingModeAlwaysTemplate)

label_string = NSMutableAttributedString.attributedStringWithAttachment(attachment)
label_string.appendAttributedString(NSMutableAttributedString.alloc.initWithString('my text', attributes: { NSFontAttributeName => UIFont.preferredFontForTextStyle(UIFontTextStyleFootnote), NSForegroundColorAttributeName => foreground_color }))

label = UILabel.alloc.initWithFrame(CGRectZero)
label.tintColor = foreground_color
label.attributedText = label_string
label.textAlignment = NSTextAlignmentCenter
label.numberOfLines = 0
Run Code Online (Sandbox Code Playgroud)

小智 36

似乎UIKit中存在一个错误.有一个解决方法;]

出于某种原因,您需要在图像附加之前附加空白空间以使其正常工作UIImageRenderingModeAlwaysTemplate.

所以你的片段看起来就像那样(我的是在ObjC中):

- (NSAttributedString *)attributedStringWithValue:(NSString *)string image:(UIImage *)image {
    NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
    attachment.image = image;

    NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:attachment];
    NSMutableAttributedString *mutableAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:[[NSAttributedString alloc] initWithString:@" "]];
    [mutableAttributedString appendAttributedString:attachmentString];
    [mutableAttributedString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:0] range:NSMakeRange(0, mutableAttributedString.length)]; // Put font size 0 to prevent offset
    [mutableAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:NSMakeRange(0, mutableAttributedString.length)];
    [mutableAttributedString appendAttributedString:[[NSAttributedString alloc] initWithString:@" "]];

    NSAttributedString *ratingText = [[NSAttributedString alloc] initWithString:string];
    [mutableAttributedString appendAttributedString:ratingText];
    return mutableAttributedString;
}
Run Code Online (Sandbox Code Playgroud)

  • 将空格添加到布局中时,可以使用空字符串而不是空格.[[NSMutableAttributedString alloc] initWithAttributedString:[[NSAttributedString alloc] initWithString:@"\ 0"]]; (3认同)

Ste*_*mer 11

UIImage+Additions在调整UIImage的时候,我有很好的使用库的经验.你可以在这里找到它:https://github.com/vilanovi/UIImage-Additions.特别检查第四节.

如果无法添加第三方库,可以使用以下内容:

- (UIImage *)colorImage:(UIImage *)image color:(UIColor *)color
{
    UIGraphicsBeginImageContextWithOptions(image.size, NO, [UIScreen mainScreen].scale);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextTranslateCTM(context, 0, image.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);

    CGContextSetBlendMode(context, kCGBlendModeNormal);
    CGContextDrawImage(context, rect, image.CGImage);
    CGContextSetBlendMode(context, kCGBlendModeSourceIn);
    [color setFill];
    CGContextFillRect(context, rect);


    UIImage *coloredImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return coloredImage;
}
Run Code Online (Sandbox Code Playgroud)

这将使UIImage从: 在着色之前的UIImage

着色后的UIImage

更新:Swift版本:

func colorImage(with color: UIColor) -> UIImage? {
    guard let cgImage = self.cgImage else { return nil }
    UIGraphicsBeginImageContext(self.size)
    let contextRef = UIGraphicsGetCurrentContext()

    contextRef?.translateBy(x: 0, y: self.size.height)
    contextRef?.scaleBy(x: 1.0, y: -1.0)
    let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)

    contextRef?.setBlendMode(CGBlendMode.normal)
    contextRef?.draw(cgImage, in: rect)
    contextRef?.setBlendMode(CGBlendMode.sourceIn)
    color.setFill()
    contextRef?.fill(rect)

    let coloredImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return coloredImage
}
Run Code Online (Sandbox Code Playgroud)

  • 我注意到应用这些更改后图像变得有点模糊。知道如何解决这个问题吗?我也在用pdf。 (4认同)

小智 9

let imageAttachment = NSTextAttachment()
imageAttachment.image = UIImage(systemName: "magnifyingglass")
imageAttachment.image = imageAttachment.image?.withTintColor(UIColor(red: 1.00, green: 1.00, blue: 0.00, alpha: 1.00))
Run Code Online (Sandbox Code Playgroud)

这应该有效(ios 13 及更高版本)


Zhe*_*ich 5

我将此NSMutableAttributedString扩展用于 Swift。

extension NSMutableAttributedString {
    func addImageAttachment(image: UIImage, font: UIFont, textColor: UIColor, size: CGSize? = nil) {
        let textAttributes: [NSAttributedString.Key: Any] = [
            .strokeColor: textColor,
            .foregroundColor: textColor,
            .font: font
        ]

        self.append(
            NSAttributedString.init(
                //U+200C (zero-width non-joiner) is a non-printing character. It will not paste unnecessary space.
                string: "\u{200c}",
                attributes: textAttributes
            )
        )

        let attachment = NSTextAttachment()
        attachment.image = image.withRenderingMode(.alwaysTemplate)
        //Uncomment to set size of image. 
        //P.S. font.capHeight sets height of image equal to font size.
        //let imageSize = size ?? CGSize.init(width: font.capHeight, height: font.capHeight)
        //attachment.bounds = CGRect(
        //    x: 0,
        //    y: 0,
        //    width: imageSize.width,
        //    height: imageSize.height
        //)
        let attachmentString = NSMutableAttributedString(attachment: attachment)
        attachmentString.addAttributes(
            textAttributes,
            range: NSMakeRange(
                0,
                attachmentString.length
            )
        )
        self.append(attachmentString)
    }
}
Run Code Online (Sandbox Code Playgroud)

这是如何使用它。

let attributedString = NSMutableAttributedString()
if let image = UIImage.init(named: "image") {
    attributedString.addImageAttachment(image: image, font: .systemFont(ofSize: 14), textColor: .red)
}
Run Code Online (Sandbox Code Playgroud)

您还可以将addImageAttachment的参数更改image: UIImageimage: UIImage?并检查扩展中的可空性。