@@ -83,6 +83,11 @@ final class AnimatedImageConfiguration: ObservableObject {
8383 var indicator : SDWebImageIndicator ?
8484 var transition : SDWebImageTransition ?
8585 var placeholder : PlatformImage ?
86+ var placeholderView : PlatformView ? {
87+ didSet {
88+ oldValue? . removeFromSuperview ( )
89+ }
90+ }
8691}
8792
8893/// 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 {
203208 return
204209 }
205210 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+ }
206216 view. wrapped. sd_setImage ( with: imageModel. url, placeholderImage: imageConfiguration. placeholder, options: imageModel. webOptions, context: imageModel. webContext, progress: { ( receivedSize, expectedSize, _) in
207217 let progress : Double
208218 if ( expectedSize > 0 ) {
@@ -230,8 +240,10 @@ public struct AnimatedImage : PlatformViewRepresentable {
230240 self . imageLoading. isLoading = false
231241 self . imageLoading. progress = 1
232242 if let image = image {
243+ self . imageConfiguration. placeholderView? . isHidden = true
233244 self . imageHandler. successBlock ? ( image, cacheType)
234245 } else {
246+ self . imageConfiguration. placeholderView? . isHidden = false
235247 self . imageHandler. failureBlock ? ( error ?? NSError ( ) )
236248 }
237249 }
@@ -263,6 +275,21 @@ public struct AnimatedImage : PlatformViewRepresentable {
263275 } else if let url = imageModel. url, url != view. wrapped. sd_imageURL {
264276 view. wrapped. sd_imageIndicator = imageConfiguration. indicator
265277 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+ }
266293 loadImage ( view, context: context)
267294 }
268295
@@ -728,8 +755,21 @@ extension AnimatedImage {
728755
729756 /// Associate a placeholder when loading image with url
730757 /// - 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
733773 return self
734774 }
735775
0 commit comments