Skip to content

Commit 4929f30

Browse files
authored
Merge pull request #34 from SDWebImage/fix_animatedImage_aspect_ratio
Implements the AnimatedImage's aspectRatio method, which match the SwiftUI.Image behavior.
2 parents a2f0b2d + 07787e0 commit 4929f30

File tree

1 file changed

+20
-11
lines changed

1 file changed

+20
-11
lines changed

SDWebImageSwiftUI/Classes/AnimatedImage.swift

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -269,12 +269,11 @@ public struct AnimatedImage : PlatformViewRepresentable {
269269

270270
func layoutView(_ view: AnimatedImageViewWrapper, context: PlatformViewRepresentableContext<AnimatedImage>) {
271271
// AspectRatio
272-
if let _ = imageLayout.aspectRatio {
273-
// TODO: Needs layer transform and geometry calculation
274-
}
272+
// If `aspectRatio` is `nil`, the resulting view maintains this view's aspect ratio.
273+
let contentMode: ContentMode = imageLayout.aspectRatio == nil ? .fit : .fill
275274

276275
// ContentMode
277-
switch imageLayout.contentMode {
276+
switch contentMode {
278277
case .fit:
279278
#if os(macOS)
280279
view.wrapped.imageScaling = .scaleProportionallyUpOrDown
@@ -471,10 +470,18 @@ extension AnimatedImage {
471470
/// fill the parent context.
472471
/// - Returns: A view that constrains this view's dimensions to
473472
/// `aspectRatio`, using `contentMode` as its scaling algorithm.
474-
public func aspectRatio(_ aspectRatio: CGFloat? = nil, contentMode: ContentMode) -> AnimatedImage {
473+
public func aspectRatio(_ aspectRatio: CGFloat? = nil, contentMode: ContentMode) -> some View {
474+
// The `SwifUI.View.aspectRatio(_:contentMode:)` says:
475+
// If `aspectRatio` is `nil`, the resulting view maintains this view's aspect ratio
476+
// But 1: there are no public API to declare what `this view's aspect ratio` is
477+
// So, if we don't override this method, SwiftUI ignore the content mode on actual ImageView
478+
// To workaround, we want to call the default `SwifUI.View.aspectRatio(_:contentMode:)` method
479+
// But 2: there are no way to call a Protocol Extention default implementation in Swift 5.1
480+
// So, we need a hack, that create a empty modifier, they call method on that view instead
481+
// Fired Radar: FB7413534
475482
imageLayout.aspectRatio = aspectRatio
476483
imageLayout.contentMode = contentMode
477-
return self
484+
return self.modifier(EmptyModifier()).aspectRatio(aspectRatio, contentMode: contentMode)
478485
}
479486

480487
/// Constrains this view's dimensions to the aspect ratio of the given size.
@@ -485,26 +492,28 @@ extension AnimatedImage {
485492
/// fill the parent context.
486493
/// - Returns: A view that constrains this view's dimensions to
487494
/// `aspectRatio`, using `contentMode` as its scaling algorithm.
488-
public func aspectRatio(_ aspectRatio: CGSize, contentMode: ContentMode) -> AnimatedImage {
495+
public func aspectRatio(_ aspectRatio: CGSize, contentMode: ContentMode) -> some View {
489496
var ratio: CGFloat?
490497
if aspectRatio.width > 0 && aspectRatio.height > 0 {
491498
ratio = aspectRatio.width / aspectRatio.height
499+
} else {
500+
NSException(name: .invalidArgumentException, reason: "\(type(of: self)).\(#function) should be called with positive aspectRatio", userInfo: nil).raise()
492501
}
493502
return self.aspectRatio(ratio, contentMode: contentMode)
494503
}
495504

496505
/// Scales this view to fit its parent.
497506
/// - Returns: A view that scales this view to fit its parent,
498507
/// maintaining this view's aspect ratio.
499-
public func scaledToFit() -> AnimatedImage {
500-
self.aspectRatio(nil, contentMode: .fit)
508+
public func scaledToFit() -> some View {
509+
return self.aspectRatio(nil, contentMode: .fit)
501510
}
502511

503512
/// Scales this view to fill its parent.
504513
/// - Returns: A view that scales this view to fit its parent,
505514
/// maintaining this view's aspect ratio.
506-
public func scaledToFill() -> AnimatedImage {
507-
self.aspectRatio(nil, contentMode: .fill)
515+
public func scaledToFill() -> some View {
516+
return self.aspectRatio(nil, contentMode: .fill)
508517
}
509518
}
510519

0 commit comments

Comments
 (0)