Skip to content

Commit f7986ad

Browse files
committed
Re-implements the AnimatedImage scale mode using the correct logic compared with SwiftUI.Image
1 parent 27e8288 commit f7986ad

File tree

1 file changed

+53
-19
lines changed

1 file changed

+53
-19
lines changed

SDWebImageSwiftUI/Classes/AnimatedImage.swift

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ final class AnimatedImageCoordinator : ObservableObject {
2828

2929
// Layout Binding Object
3030
final class AnimatedImageLayout : ObservableObject {
31-
@Published var contentMode: ContentMode = .fill
31+
@Published var contentMode: ContentMode?
3232
@Published var aspectRatio: CGFloat?
3333
@Published var capInsets: EdgeInsets = EdgeInsets()
3434
@Published var resizingMode: Image.ResizingMode?
@@ -268,30 +268,64 @@ public struct AnimatedImage : PlatformViewRepresentable {
268268
}
269269

270270
func layoutView(_ view: AnimatedImageViewWrapper, context: PlatformViewRepresentableContext<AnimatedImage>) {
271-
// AspectRatio
272-
// If `aspectRatio` is `nil`, the resulting view maintains this view's aspect ratio.
273-
let contentMode: ContentMode = imageLayout.aspectRatio == nil ? .fit : .fill
274-
275-
// ContentMode
276-
switch contentMode {
277-
case .fit:
278-
#if os(macOS)
279-
view.wrapped.imageScaling = .scaleProportionallyUpOrDown
280-
#elseif os(iOS) || os(tvOS)
281-
view.wrapped.contentMode = .scaleAspectFit
282-
#elseif os(watchOS)
283-
view.wrapped.setContentMode(.aspectFit)
284-
#endif
285-
case .fill:
271+
// AspectRatio && ContentMode
272+
#if os(macOS)
273+
let contentMode: NSImageScaling
274+
#elseif os(iOS) || os(tvOS)
275+
let contentMode: UIView.ContentMode
276+
#elseif os(watchOS)
277+
let contentMode: SDImageScaleMode
278+
#endif
279+
if let _ = imageLayout.aspectRatio {
280+
// If `aspectRatio` is not `nil`, always scale to fill and SwiftUI will layout the container with custom aspect ratio.
286281
#if os(macOS)
287-
view.wrapped.imageScaling = .scaleAxesIndependently
282+
contentMode = .scaleAxesIndependently
288283
#elseif os(iOS) || os(tvOS)
289-
view.wrapped.contentMode = .scaleToFill
284+
contentMode = .scaleToFill
290285
#elseif os(watchOS)
291-
view.wrapped.setContentMode(.fill)
286+
contentMode = .fill
292287
#endif
288+
} else {
289+
// If `aspectRatio` is `nil`, the resulting view maintains this view's aspect ratio.
290+
switch imageLayout.contentMode {
291+
case .fill:
292+
#if os(macOS)
293+
// Actually, NSImageView have no `.aspectFill` unlike UIImageView, only `CALayerContentsGravity.resizeAspectFill` have the same concept, but it does not work here
294+
// TODO: Need SwiftUI officialy provide a solution
295+
contentMode = .scaleProportionallyUpOrDown
296+
#elseif os(iOS) || os(tvOS)
297+
contentMode = .scaleAspectFill
298+
#elseif os(watchOS)
299+
contentMode = .aspectFill
300+
#endif
301+
case .fit:
302+
#if os(macOS)
303+
contentMode = .scaleProportionallyUpOrDown
304+
#elseif os(iOS) || os(tvOS)
305+
contentMode = .scaleAspectFit
306+
#elseif os(watchOS)
307+
contentMode = .aspectFit
308+
#endif
309+
case .none:
310+
// If `contentMode` is not set at all, using scale to fill as SwiftUI default value
311+
#if os(macOS)
312+
contentMode = .scaleAxesIndependently
313+
#elseif os(iOS) || os(tvOS)
314+
contentMode = .scaleToFill
315+
#elseif os(watchOS)
316+
contentMode = .fill
317+
#endif
318+
}
293319
}
294320

321+
#if os(macOS)
322+
view.wrapped.imageScaling = contentMode
323+
#elseif os(iOS) || os(tvOS)
324+
view.wrapped.contentMode = contentMode
325+
#elseif os(watchOS)
326+
view.wrapped.setContentMode(contentMode)
327+
#endif
328+
295329
// Animated Image does not support resizing mode and rendering mode
296330
if let image = imageModel.image, !image.sd_isAnimated, !image.conforms(to: SDAnimatedImageProtocol.self) {
297331
var image = image

0 commit comments

Comments
 (0)