Now this should work. "color" is the full color PNG, "alpha" is a transparent PNG. It's blurry on the X-Large watch face but because the watch face requests the wrong resolution. You can do a 2x on the scale however that will break the other complications.
Maybe there is a way to know that the Watch requests the icon for the X-Large watch face but I stopped caring, it's stupid to spend so much time on something that simple, not gonna touch this again
import SwiftUI
import WidgetKit
@main
struct IconBundle: WidgetBundle {
@WidgetBundleBuilder
var body: some Widget {
IconWidget()
InlineWidget()
}
}
struct IconProvider: TimelineProvider {
func placeholder(in context: Context) -> IconEntry {
return IconEntry(context: context)
}
func getSnapshot(in context: Context, completion: @escaping (IconEntry) -> ()) {
let entry = IconEntry(context: context)
completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
let entry = IconEntry(context: context)
let timeline = Timeline(entries: [entry], policy: .never)
completion(timeline)
}
}
struct IconWidget: Widget {
let kind: String = "IconWidget"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: IconProvider()) { entry in
IconView(entry: entry)
.containerBackground(Color.clear, for: .widget)
}
.supportedFamilies([.accessoryCircular, .accessoryCorner, .accessoryRectangular])
.description(Text("Description"))
}
}
struct InlineWidget: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(kind: "Inline", provider: IconProvider()) { entry in
Text("App Title")
}
.configurationDisplayName("App Title")
.description("Description")
.supportedFamilies([.accessoryInline])
}
}
struct IconView: View {
@Environment(\.widgetRenderingMode) var widgetRenderingMode
let entry: IconEntry
var body: some View {
imageFor(widgetRenderingMode, entry: entry)
.resizable()
}
}
private func imageFor(_ widgetRenderingMode: WidgetRenderingMode, entry: IconEntry) -> Image {
var image: UIImage
let size = entry.context.displaySize
switch widgetRenderingMode {
case .fullColor:
image = UIImage(imageLiteralResourceName: "color.png")
default:
image = UIImage(imageLiteralResourceName: "alpha.png")
}
return Image(uiImage: image.resizeImage(width: size.width, height: size.height))
}
struct IconEntry: TimelineEntry {
let date = Date()
let context: TimelineProviderContext
}
extension UIImage {
func resizeImage(width: CGFloat, height: CGFloat) -> UIImage {
let edgeLength = min(width, height)
let newSize = CGSize(width: edgeLength, height: edgeLength)
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
self.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
if let resizedImage = UIGraphicsGetImageFromCurrentImageContext() {
UIGraphicsEndImageContext()
return resizedImage
} else {
return UIImage()
}
}
}