Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1edee7f

Browse files
Re-implements the aspectRatio support on AnimatedImage, fix issue like cornerRadius
Use the correct way to override invalidateIntrinsicContentSize to keep aspect ratio to UIKit/SwiftUI engine
1 parent 03c468b commit 1edee7f

File tree

3 files changed

+45
-83
lines changed

3 files changed

+45
-83
lines changed

‎Example/SDWebImageSwiftUIDemo/ContentView.swift‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@ class UserSettings: ObservableObject {
1717
#endif
1818
}
1919

20+
struct ContentView4: View {
21+
var url = URL(string: "https://github.com/SDWebImage/SDWebImageSwiftUI/assets/97430818/72d27f90-e9d8-48d7-b144-82ada828a027")!
22+
var body: some View {
23+
AnimatedImage(url: url)
24+
.resizable()
25+
.scaledToFit()
26+
// .aspectRatio(nil, contentMode: .fit)
27+
.clipShape(RoundedRectangle(cornerRadius: 50, style: .continuous))
28+
}
29+
}
30+
2031
// Test Switching nil url
2132
struct ContentView3: View {
2233
@State var isOn = false

‎SDWebImageSwiftUI/Classes/AnimatedImage.swift‎

Lines changed: 20 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,9 @@ public struct AnimatedImage : PlatformViewRepresentable {
275275
self.imageModel.placeholderView?.isHidden = false
276276
self.imageHandler.failureBlock?(error ?? NSError())
277277
}
278+
// Finished loading
279+
configureView(view, context: context)
280+
layoutView(view, context: context)
278281
}
279282
}
280283

@@ -361,20 +364,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
361364
break // impossible
362365
}
363366

364-
#if os(macOS)
365-
if self.isAnimating != view.wrapped.animates {
366-
view.wrapped.animates = self.isAnimating
367-
}
368-
#else
369-
if self.isAnimating != view.wrapped.isAnimating {
370-
if self.isAnimating {
371-
view.wrapped.startAnimating()
372-
} else {
373-
view.wrapped.stopAnimating()
374-
}
375-
}
376-
#endif
377-
367+
// Finished loading
378368
configureView(view, context: context)
379369
layoutView(view, context: context)
380370
if let viewUpdateBlock = imageHandler.viewUpdateBlock {
@@ -442,9 +432,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
442432
#endif
443433

444434
// Resizable
445-
if let _ = imageLayout.resizingMode {
446-
view.resizable = true
447-
}
435+
view.resizingMode = imageLayout.resizingMode
448436

449437
// Animated Image does not support resizing mode and rendering mode
450438
if let image = view.wrapped.image {
@@ -587,6 +575,21 @@ public struct AnimatedImage : PlatformViewRepresentable {
587575
} else {
588576
view.wrapped.playbackMode = .normal
589577
}
578+
579+
// Animation
580+
#if os(macOS)
581+
if self.isAnimating != view.wrapped.animates {
582+
view.wrapped.animates = self.isAnimating
583+
}
584+
#else
585+
if self.isAnimating != view.wrapped.isAnimating {
586+
if self.isAnimating {
587+
view.wrapped.startAnimating()
588+
} else {
589+
view.wrapped.stopAnimating()
590+
}
591+
}
592+
#endif
590593
}
591594
}
592595

@@ -630,68 +633,6 @@ extension AnimatedImage {
630633
}
631634
}
632635

633-
// Aspect Ratio
634-
@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
635-
extension AnimatedImage {
636-
func setImageLayoutAspectRatio(_ aspectRatio: CGFloat?, contentMode: ContentMode) {
637-
self.imageLayout.aspectRatio = aspectRatio
638-
self.imageLayout.contentMode = contentMode
639-
}
640-
641-
/// Constrains this view's dimensions to the specified aspect ratio.
642-
/// - Parameters:
643-
/// - aspectRatio: The ratio of width to height to use for the resulting
644-
/// view. If `aspectRatio` is `nil`, the resulting view maintains this
645-
/// view's aspect ratio.
646-
/// - contentMode: A flag indicating whether this view should fit or
647-
/// fill the parent context.
648-
/// - Returns: A view that constrains this view's dimensions to
649-
/// `aspectRatio`, using `contentMode` as its scaling algorithm.
650-
@ViewBuilder
651-
public func aspectRatio(_ aspectRatio: CGFloat? = nil, contentMode: ContentMode) -> some View {
652-
// The `SwifUI.View.aspectRatio(_:contentMode:)` says:
653-
// If `aspectRatio` is `nil`, the resulting view maintains this view's aspect ratio
654-
// But 1: there are no public API to declare what `this view's aspect ratio` is
655-
// So, if we don't override this method, SwiftUI ignore the content mode on actual ImageView
656-
// To workaround, we want to call the default `SwifUI.View.aspectRatio(_:contentMode:)` method
657-
// But 2: there are no way to call a Protocol Extention default implementation in Swift 5.1
658-
// So, we directly call the implementation detail modifier instead
659-
// Fired Radar: FB7413534
660-
let _ = self.setImageLayoutAspectRatio(aspectRatio, contentMode: contentMode)
661-
if let aspectRatio {
662-
self.modifier(_AspectRatioLayout(aspectRatio: aspectRatio, contentMode: contentMode))
663-
} else {
664-
self
665-
}
666-
}
667-
668-
/// Constrains this view's dimensions to the aspect ratio of the given size.
669-
/// - Parameters:
670-
/// - aspectRatio: A size specifying the ratio of width to height to use
671-
/// for the resulting view.
672-
/// - contentMode: A flag indicating whether this view should fit or
673-
/// fill the parent context.
674-
/// - Returns: A view that constrains this view's dimensions to
675-
/// `aspectRatio`, using `contentMode` as its scaling algorithm.
676-
public func aspectRatio(_ aspectRatio: CGSize, contentMode: ContentMode) -> some View {
677-
return self.aspectRatio(aspectRatio.width / aspectRatio.height, contentMode: contentMode)
678-
}
679-
680-
/// Scales this view to fit its parent.
681-
/// - Returns: A view that scales this view to fit its parent,
682-
/// maintaining this view's aspect ratio.
683-
public func scaledToFit() -> some View {
684-
return self.aspectRatio(nil, contentMode: .fit)
685-
}
686-
687-
/// Scales this view to fill its parent.
688-
/// - Returns: A view that scales this view to fit its parent,
689-
/// maintaining this view's aspect ratio.
690-
public func scaledToFill() -> some View {
691-
return self.aspectRatio(nil, contentMode: .fill)
692-
}
693-
}
694-
695636
// AnimatedImage Modifier
696637
@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
697638
extension AnimatedImage {

‎SDWebImageSwiftUI/Classes/ImageViewWrapper.swift‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import Foundation
1010
import SDWebImage
11+
import SwiftUI
1112

1213
#if !os(watchOS)
1314

@@ -18,7 +19,7 @@ public class AnimatedImageViewWrapper : PlatformView {
1819
public var wrapped = SDAnimatedImageView()
1920
var interpolationQuality = CGInterpolationQuality.default
2021
var shouldAntialias = false
21-
var resizable=false
22+
var resizingMode:Image.ResizingMode?
2223

2324
public override func draw(_ rect: CGRect) {
2425
#if os(macOS)
@@ -48,11 +49,20 @@ public class AnimatedImageViewWrapper : PlatformView {
4849

4950
public override var intrinsicContentSize: CGSize {
5051
/// Match the behavior of SwiftUI.Image, only when image is resizable, use the super implementation to calculate size
51-
if resizable {
52-
return super.intrinsicContentSize
52+
let imageSize = wrapped.intrinsicContentSize
53+
if let _ = resizingMode {
54+
/// Keep aspect ratio
55+
let noIntrinsicMetric = AnimatedImageViewWrapper.noIntrinsicMetric
56+
if (imageSize.width > 0 && imageSize.height > 0) {
57+
let ratio = imageSize.width / imageSize.height
58+
let size = CGSize(width: ratio, height: 1)
59+
return size
60+
} else {
61+
return CGSize(width: noIntrinsicMetric, height: noIntrinsicMetric)
62+
}
5363
} else {
5464
/// Not resizable, always use image size, like SwiftUI.Image
55-
return wrapped.intrinsicContentSize
65+
return imageSize
5666
}
5767
}
5868

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /