Ort*_*ntz 13 uikit uiimage ios ios-darkmode uiuserinterfacestyle
iOS 13 引入UIImage了自动采用当前UIUserInterfaceStyle模式(又名亮或暗模式)的实例。但是,似乎只有从命名或系统映像(imageNamed:inBundle:withConfiguration:或systemImageNamed:withConfiguration:)构建此类映像的方法。
有没有办法UIImage从 Core Graphics动态生成通用明暗模式(例如使用两个CGImages 或使用 UIGraphicsImageRenderer)?
我没有看到任何 API,但也许我错了。
这是我在 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: UITraitCollection(userInterfaceStyle: .dark))
return lightImage
}
else {
return light()
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个实现:
displayScale和userInterfaceLevel)userInterfaceLevel或horizontalSizeClass,深色图像的使用也不会受到影响,当且仅当界面风格为深色时仍然使用)假设我们已经加载了两个变体:
let lightImage = ...
let darkImage = ...
let result = UIImage.dynamicImage(withLight: lightImage, dark: darkImage)
Run Code Online (Sandbox Code Playgroud)
假设我们想要一个红色图像,动态的亮/暗,只需调用:
let result = UIImage.dynamicImage(withLight: UIImage.generate(withColor: UIColor.red),
dark: UIImage.generate(withColor: UIColor.red))
Run Code Online (Sandbox Code Playgroud)
其中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()
}
}
Run Code Online (Sandbox Code Playgroud)
您不会创建新的UIImageAsset,而是从现有UIImage的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)
Run Code Online (Sandbox Code Playgroud)
或者使用这个UIImage扩展
extension UIImage {
func registerDarkImage(_ image: UIImage) {
if #available(iOS 12.0, *) {
imageAsset?.register(image, with: .init(userInterfaceStyle: .dark))
}
}
}
Run Code Online (Sandbox Code Playgroud)