Ich möchte ein 1x1 UIImage dynamisch erstellen, das auf einem UIColor basiert.
Ich vermute, dass dies mit Quartz2d schnell erledigt werden kann, und ich schaue mir die Dokumentation an, die versucht, die Grundlagen zu verstehen. Es sieht jedoch so aus, als gäbe es viele mögliche Fallstricke: Die Anzahl der Bits und Bytes pro Objekt nicht korrekt identifizieren, die richtigen Flags nicht angeben, nicht verwendete Daten nicht freigeben usw.
Wie kann dies mit Quartz 2d (oder einem anderen einfacheren Weg) sicher gemacht werden?
Sie können CGContextSetFillColorWithColor
und CGContextFillRect
dafür verwenden:
Swift
extension UIImage {
class func image(with color: UIColor) -> UIImage {
let rect = CGRectMake(0.0, 0.0, 1.0, 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(context, color.CGColor)
CGContextFillRect(context, rect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
Swift3
extension UIImage {
class func image(with color: UIColor) -> UIImage {
let rect = CGRect(Origin: CGPoint(x: 0, y:0), size: CGSize(width: 1, height: 1))
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()!
context.setFillColor(color.cgColor)
context.fill(rect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
Ziel c
+ (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Hier ist eine weitere Option, die auf dem Code von Matt Stephen basiert. Dadurch wird ein einfarbig skalierbares Bild erstellt, sodass Sie es wiederverwenden oder seine Größe ändern können (z. B. als Hintergrund).
+ (UIImage *)prefix_resizeableImageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 3.0f, 3.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(1, 1, 1, 1)];
return image;
}
Fügen Sie es in eine UIImage-Kategorie ein und ändern Sie das Präfix.
Ich habe die Antwort von Matt Steven oft verwendet und machte dafür eine Kategorie:
@interface UIImage (mxcl)
+ (UIImage *)squareImageWithColor:(UIColor *)color dimension:(int)dimension;
@end
@implementation UIImage (mxcl)
+ (UIImage *)squareImageWithColor:(UIColor *)color dimension:(int)dimension {
CGRect rect = CGRectMake(0, 0, dimension, dimension);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
@end
Mit dem neuesten UIGraphicsImageRenderer von Apple ist der Code ziemlich klein:
import UIKit
extension UIImage {
static func from(color: UIColor) -> UIImage {
let size = CGSize(width: 1, height: 1)
return UIGraphicsImageRenderer(size: size).image(actions: { (context) in
context.cgContext.setFillColor(color.cgColor)
context.fill(.init(Origin: .zero, size: size))
})
}
}
Für mich fühlt sich eine Bequemlichkeit in Swift netter an.
extension UIImage {
convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
UIGraphicsBeginImageContext(rect.size)
guard let context = UIGraphicsGetCurrentContext() else {
return nil
}
context.setFillColor(color.cgColor)
context.fill(rect)
guard let image = context.makeImage() else {
return nil
}
UIGraphicsEndImageContext()
self.init(cgImage: image)
}
}