Add the scaleToFit/Fill method to AnimatedImageView, refactory the implementation to use binding

This commit is contained in:
DreamPiggy 2019-09-25 03:07:00 +08:00
parent 875c813b39
commit 058915b56d
2 changed files with 71 additions and 28 deletions

View File

@ -16,10 +16,10 @@ struct ContentView: View {
VStack {
WebImage(url: URL(string: "https://nokiatech.github.io/heif/content/images/ski_jump_1440x960.heic"))
.scaledToFit()
.frame(width: 300, height: 300, alignment: .center)
AnimatedImage(url: URL(string: "https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif"))
// .scaledToFit() // Apple's Bug ? Custom UIView does not passthrough the `contentMode` from Swift UI layout system into UIKit layout system
.frame(width: 400, height: 300, alignment: .center)
.frame(width: CGFloat(300), height: CGFloat(300), alignment: .center)
AnimatedImage(url: URL(string: "https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif"), options: [.progressiveLoad])
.scaledToFill()
.frame(width: CGFloat(400), height: CGFloat(300), alignment: .center)
}
}
}

View File

@ -11,12 +11,24 @@ import SDWebImage
#if !os(watchOS)
// Data Binding Object
final class AnimatedImageModel : ObservableObject {
@Published var image: SDAnimatedImage?
@Published var url: URL?
}
// Layout Binding Object
final class AnimatedImageLayout : ObservableObject {
@Published var contentMode: ContentMode = .fill
}
// View
public struct AnimatedImage : ViewRepresentable {
var url: URL?
var name: String?
var bundle: Bundle?
var data: Data?
var scale: CGFloat = 0
@ObservedObject var imageModel = AnimatedImageModel()
@ObservedObject var imageLayout = AnimatedImageLayout()
var webOptions: SDWebImageOptions = []
var webContext: [SDWebImageContextOption : Any]? = nil
#if os(macOS)
public typealias NSViewType = SDAnimatedImageView
@ -47,36 +59,67 @@ public struct AnimatedImage: ViewRepresentable {
}
func updateView(_ view: SDAnimatedImageView, context: ViewRepresentableContext<AnimatedImage>) {
if let url = url {
view.sd_setImage(with: url)
return
view.image = imageModel.image
if let url = imageModel.url {
view.sd_setImage(with: url, placeholderImage: view.image, options: webOptions, context: webContext)
}
if let name = name {
switch imageLayout.contentMode {
case .fit:
#if os(macOS)
view.image = SDAnimatedImage(named: name, in: bundle)
view.imageScaling = .scaleProportionallyUpOrDown
#else
view.image = SDAnimatedImage(named: name, in: bundle, compatibleWith: nil)
view.contentMode = .scaleAspectFit
#endif
case .fill:
#if os(macOS)
view.imageScaling = .scaleAxesIndependently
#else
view.contentMode = .scaleToFill
#endif
return
}
if let data = data {
view.image = SDAnimatedImage(data: data, scale: scale)
return
}
}
public init(url: URL?, placeholder: Image? = nil, options: SDWebImageOptions = [], context: [SDWebImageContextOption : Any]? = nil) {
self.url = url
public func image(_ image: SDAnimatedImage?) -> Self {
imageModel.image = image
return self
}
public func imageUrl(_ url: URL?) -> Self {
imageModel.url = url
return self
}
public func scaledToFit() -> Self {
imageLayout.contentMode = .fit
return self
}
public func scaledToFill() -> Self {
imageLayout.contentMode = .fill
return self
}
}
extension AnimatedImage {
public init(url: URL?, placeholder: SDAnimatedImage? = nil, options: SDWebImageOptions = [], context: [SDWebImageContextOption : Any]? = nil) {
self.webOptions = options
self.webContext = context
self.imageModel.url = url
}
public init(name: String, bundle: Bundle? = nil) {
self.name = name
self.bundle = bundle
#if os(macOS)
let image = SDAnimatedImage(named: name, in: bundle)
#else
let image = SDAnimatedImage(named: name, in: bundle, compatibleWith: nil)
#endif
self.imageModel.image = image
}
public init(data: Data, scale: CGFloat = 0) {
self.data = data
self.scale = scale
let image = SDAnimatedImage(data: data, scale: scale)
self.imageModel.image = image
}
}