Skip to content

Implements the AnimatedImage's aspectRatio method, which match the SwiftUI.Image behavior. #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 28, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions SDWebImageSwiftUI/Classes/AnimatedImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,11 @@ public struct AnimatedImage : PlatformViewRepresentable {

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

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

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

/// Scales this view to fit its parent.
/// - Returns: A view that scales this view to fit its parent,
/// maintaining this view's aspect ratio.
public func scaledToFit() -> AnimatedImage {
self.aspectRatio(nil, contentMode: .fit)
public func scaledToFit() -> some View {
return self.aspectRatio(nil, contentMode: .fit)
}

/// Scales this view to fill its parent.
/// - Returns: A view that scales this view to fit its parent,
/// maintaining this view's aspect ratio.
public func scaledToFill() -> AnimatedImage {
self.aspectRatio(nil, contentMode: .fill)
public func scaledToFill() -> some View {
return self.aspectRatio(nil, contentMode: .fill)
}
}

Expand Down