@@ -83,6 +83,11 @@ final class AnimatedImageConfiguration: ObservableObject {
83
83
var indicator : SDWebImageIndicator ?
84
84
var transition : SDWebImageTransition ?
85
85
var placeholder : PlatformImage ?
86
+ var placeholderView : PlatformView ? {
87
+ didSet {
88
+ oldValue? . removeFromSuperview ( )
89
+ }
90
+ }
86
91
}
87
92
88
93
/// A Image View type to load image from url, data or bundle. Supports animated and static image format.
@@ -203,6 +208,11 @@ public struct AnimatedImage : PlatformViewRepresentable {
203
208
return
204
209
}
205
210
self . imageLoading. isLoading = true
211
+ if imageModel. webOptions. contains ( . delayPlaceholder) {
212
+ self . imageConfiguration. placeholderView? . isHidden = true
213
+ } else {
214
+ self . imageConfiguration. placeholderView? . isHidden = false
215
+ }
206
216
view. wrapped. sd_setImage ( with: imageModel. url, placeholderImage: imageConfiguration. placeholder, options: imageModel. webOptions, context: imageModel. webContext, progress: { ( receivedSize, expectedSize, _) in
207
217
let progress : Double
208
218
if ( expectedSize > 0 ) {
@@ -230,8 +240,10 @@ public struct AnimatedImage : PlatformViewRepresentable {
230
240
self . imageLoading. isLoading = false
231
241
self . imageLoading. progress = 1
232
242
if let image = image {
243
+ self . imageConfiguration. placeholderView? . isHidden = true
233
244
self . imageHandler. successBlock ? ( image, cacheType)
234
245
} else {
246
+ self . imageConfiguration. placeholderView? . isHidden = false
235
247
self . imageHandler. failureBlock ? ( error ?? NSError ( ) )
236
248
}
237
249
}
@@ -263,6 +275,21 @@ public struct AnimatedImage : PlatformViewRepresentable {
263
275
} else if let url = imageModel. url, url != view. wrapped. sd_imageURL {
264
276
view. wrapped. sd_imageIndicator = imageConfiguration. indicator
265
277
view. wrapped. sd_imageTransition = imageConfiguration. transition
278
+ if let placeholderView = imageConfiguration. placeholderView {
279
+ placeholderView. removeFromSuperview ( )
280
+ placeholderView. isHidden = true
281
+ // Placeholder View should below the Indicator View
282
+ if let indicatorView = imageConfiguration. indicator? . indicatorView {
283
+ #if os(macOS)
284
+ view. wrapped. addSubview ( placeholderView, positioned: . below, relativeTo: indicatorView)
285
+ #else
286
+ view. wrapped. insertSubview ( placeholderView, belowSubview: indicatorView)
287
+ #endif
288
+ } else {
289
+ view. wrapped. addSubview ( placeholderView)
290
+ }
291
+ placeholderView. bindFrameToSuperviewBounds ( )
292
+ }
266
293
loadImage ( view, context: context)
267
294
}
268
295
@@ -728,8 +755,21 @@ extension AnimatedImage {
728
755
729
756
/// Associate a placeholder when loading image with url
730
757
/// - Parameter content: A view that describes the placeholder.
731
- public func placeholder( _ placeholder: PlatformImage ? ) -> AnimatedImage {
732
- self . imageConfiguration. placeholder = placeholder
758
+ /// - note: The differences between this and placeholder image, it's that placeholder image replace the image for image view, but this modify the View Hierarchy to overlay the placeholder hosting view
759
+ public func placeholder< T> ( @ViewBuilder content: ( ) -> T ) -> AnimatedImage where T : View {
760
+ #if os(macOS)
761
+ let hostingView = NSHostingView ( rootView: content ( ) )
762
+ #else
763
+ let hostingView = _UIHostingView ( rootView: content ( ) )
764
+ #endif
765
+ self . imageConfiguration. placeholderView = hostingView
766
+ return self
767
+ }
768
+
769
+ /// Associate a placeholder image when loading image with url
770
+ /// - Parameter content: A view that describes the placeholder.
771
+ public func placeholder( _ image: PlatformImage ? ) -> AnimatedImage {
772
+ self . imageConfiguration. placeholder = image
733
773
return self
734
774
}
735
775
0 commit comments