iOS 13引入了UIImage
实例,它们自动采用当前的UIUserInterfaceStyle
(即亮模式或暗模式)。但是,似乎只有一些方法可以从命名或系统映像(imageNamed:inBundle:withConfiguration:
或systemImageNamed:withConfiguration:
)中构造此类映像。
是否可以通过Core Graphics动态生成通用的明暗模式UIImage
(例如,使用两个CGImage
或使用UIGraphicsImageRenderer)?
我看不到任何API,但也许我错了。
答案 0 :(得分:4)
前几天对此做了一些研究(也需要此功能,但到目前为止尚未实现):
UIImageAsset
register(_:with:)
中的UIImageAsset
(提供userInterfaceStyle .dark / .light)作为特征收集参数https://developer.apple.com/documentation/uikit/uiimageasset/1624974-register 答案 1 :(得分:2)
+ (UIImage*)dynamicImageWithNormalImage:(UIImage*)normalImage darkImage:(UIImage*)darkImage{
if (normalImage == nil || darkImage == nil) {
return normalImage ? : darkImage;
}
if (@available(iOS 13.0, *)) {
UIImageAsset* imageAseset = [[UIImageAsset alloc]init];
// 注册 lightImage
UITraitCollection* lightImageTrateCollection = [UITraitCollection traitCollectionWithTraitsFromCollections:
@[[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight],
[UITraitCollection traitCollectionWithDisplayScale:normalImage.scale]]];
[imageAseset registerImage:normalImage withTraitCollection:lightImageTrateCollection];
// 注册 darkImage
UITraitCollection* darkImageTrateCollection = [UITraitCollection traitCollectionWithTraitsFromCollections:
@[[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleDark],
[UITraitCollection traitCollectionWithDisplayScale:darkImage.scale]]];
[imageAseset registerImage:darkImage withTraitCollection:darkImageTrateCollection];
return [imageAseset imageWithTraitCollection:[UITraitCollection currentTraitCollection]];
}
else {
return normalImage;
}
}
也许就是您想要的。
答案 2 :(得分:2)
您无需创建新的UIImageAsset
,而是从现有UIImage
的{{1}}属性中引用一个属性,并在其中添加一个黑色使用imageAsset
方法的图片变体。
UIImageAsset.register(_:with:)
或使用此
// Prepare a UIImage for light mode.
let lightImage: UIImage!
// Prepare a UIImage for dark mode.
let darkImage: UIImage!
// Register your dark mode image to the light mode image's image asset.
lightImage?.imageAsset?.register(darkImage, with: .init(userInterfaceStyle: .dark))
// Now your light mode image actually becomes a dynamic image. Use it.
someImageView.image = lightImage
someButton.setImage(lightImage, for: .normal)
扩展名
UIImage
答案 3 :(得分:1)
这是我在Swift 5中的实现
extension UIImage {
static func dynamicImage(withLight light: @autoclosure () -> UIImage,
dark: @autoclosure () -> UIImage) -> UIImage {
if #available(iOS 13.0, *) {
let lightTC = UITraitCollection(traitsFrom: [.current, .init(userInterfaceStyle: .light)])
let darkTC = UITraitCollection(traitsFrom: [.current, .init(userInterfaceStyle: .dark)])
var lightImage = UIImage()
var darkImage = UIImage()
lightTC.performAsCurrent {
lightImage = light()
}
darkTC.performAsCurrent {
darkImage = dark()
}
lightImage.imageAsset?.register(darkImage, with: darkTC)
return lightImage
}
else {
return light()
}
}
}
此实现:
displayScale
和userInterfaceLevel
)假设我们已经加载了两个变体:
let lightImage = ...
let darkImage = ...
let result = UIImage.dynamicImage(withLight: lightImage, dark: darkImage)
假设我们想要一张红色的图像,可以动态显示明暗,只需调用:
let result = UIImage.dynamicImage(withLight: UIImage.generate(withColor: UIColor.red),
dark: UIImage.generate(withColor: UIColor.red))
其中generate
的功能如下:
extension UIImage {
static func generate(withColor color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context?.setFillColor(color.cgColor)
context?.fill(rect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image ?? UIImage()
}
}