属性付き文字列の添付ファイルであるテンプレート画像の色を設定するにはどうすればよいですか?
バックグラウンド:
UILabelがあり、そのattributedTextを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
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;
}
ライブラリの使用経験は豊富ですUIImage+Additions
UIImageを着色する場合。あなたはそれをここで見つけることができます: https://github.com/vilanovi/UIImage-Additions 。特にセクションIVを確認してください。
サードパーティのライブラリを追加できない場合は、次の方法で開始できます。
- (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;
}
これにより、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
}
私はより良い解決策を見つけました。最初の項目にプレーンテキストが含まれていることを確認してください。 NSTextAttachment
(画像)が最初のアイテムである場合、NSTextAttachment
の前にスペース文字列を挿入できます。
// create image attachment
NSTextAttachment *imageAttachment = [[NSTextAttachment alloc] init];
imageAttachment.image = [[UIImage imageNamed:@"ImageName"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
NSAttributedString *imageAttchString = [NSAttributedString attributedStringWithAttachment:attachment];
// create attributedString
NSString *string = @"Some text ";
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
// insert image
[attributedString insertAttributedString:imageAttchString atIndex:0];
[attributedString insertAttributedString:[[NSAttributedString alloc] initWithString:@" "] atIndex:0];
label.attributedText = attributedString;
// used
label.textColor = [UIColor redColor];
// or
label.textColor = [UIColor greenColor];
@blazejmarによる解決策は機能しますが、不要です。これが機能するために必要なことは、属性付き文字列が接続された後に色を設定することだけです。ここに例があります。
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
attachment.image = [[UIImage imageNamed:@"ImageName"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:attachment];
NSString *string = @"Some text ";
NSRange range2 = NSMakeRange(string.length - 1, attachmentString.length);
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
[attributedString appendAttributedString:attachmentString];
[attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:range2];
self.label.attributedText = attributedString;
IOS 12では、画像の前に文字を挿入し、その文字に前景色を設定する必要があります。ただし、iOS 13では、NSTextAttachmentを含むNSAttributedStringに直接前景色を設定できます。
IOS 12.3およびiOS 13.3.1で次の拡張機能をテストしました
extension NSMutableAttributedString {
@discardableResult
func sbs_append(_ image: UIImage, color: UIColor? = nil) -> Self {
let attachment = NSTextAttachment()
attachment.image = image
let attachmentString = NSAttributedString(attachment: attachment)
if let color = color {
if #available(iOS 13, *) {} else {
// On iOS 12 we need to add a character with a foreground color before the image,
// in order for the image to get a color.
let colorString = NSMutableAttributedString(string: "\0")
colorString.addAttributes([.foregroundColor: color], range: NSRange(location: 0, length: colorString.length))
append(colorString)
}
let attributedString = NSMutableAttributedString(attributedString: attachmentString)
if #available(iOS 13, *) {
// On iOS 13 we can set the foreground color of the image.
attributedString.addAttributes([.foregroundColor: color], range: NSRange(location: 0, length: attributedString.length))
}
append(attributedString)
} else {
append(attachmentString)
}
return self
}
}
私はSwiftにこのNSMutableAttributedString
拡張機能を使用しています。
import UIKit
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)
}
}
これがその使い方です。
let attributedString = NSMutableAttributedString()
if let image = UIImage.init(named: "image") {
attributedString.addImageAttachment(image: image, font: .systemFont(ofSize: 14), textColor: .red)
}
addImageAttachment
のパラメータimage: UIImage
をimage: UIImage?
に変更して、拡張機能のnullの可能性を確認することもできます。