Skip to content

Update with the playbackMode support for WebImage and AnimatedImage #168

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 1 commit into from
Feb 23, 2021
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ var body: some View {
// The initial value of binding should be true
.customLoopCount(1) // Custom loop count
.playbackRate(2.0) // Playback speed rate
.playbackMode(.bounce) // Playback normally to the end, then reversely back to the start
// `WebImage` supports advanced control just like `AnimatedImage`, but without the progressive animation support
}
```
Expand Down
26 changes: 15 additions & 11 deletions SDWebImageSwiftUI/Classes/AnimatedImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ final class AnimatedImageConfiguration: ObservableObject {
var pausable: Bool?
var purgeable: Bool?
var playbackRate: Double?
var playbackMode: SDAnimatedImagePlaybackMode?
// These configurations only useful for web image loading
var indicator: SDWebImageIndicator?
var transition: SDWebImageTransition?
Expand Down Expand Up @@ -253,7 +254,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
} else {
// This is a hack because of iOS 13's SwiftUI bug, the @Published does not trigger another `updateUIView` call
// Here I have to use UIKit/AppKit API to triger the same effect (the window change implicitly cause re-render)
if let hostingView = AnimatedImage.findHostingView(from: view) {
if let hostingView = view.findHostingView() {
if let _ = hostingView.window {
#if os(macOS)
hostingView.viewDidMoveToWindow()
Expand Down Expand Up @@ -542,17 +543,13 @@ public struct AnimatedImage : PlatformViewRepresentable {
} else {
view.wrapped.playbackRate = 1.0
}
}

private static func findHostingView(from entry: PlatformView) -> PlatformView? {
var superview = entry.superview
while let s = superview {
if NSStringFromClass(type(of: s)).contains("HostingView") {
return s
}
superview = s.superview

// Playback Mode
if let playbackMode = imageConfiguration.playbackMode {
view.wrapped.playbackMode = playbackMode
} else {
view.wrapped.playbackMode = .normal
}
return nil
}
}

Expand Down Expand Up @@ -717,6 +714,13 @@ extension AnimatedImage {
self.imageConfiguration.playbackRate = playbackRate
return self
}

/// Control the animation playback mode. Default is .normal
/// - Parameter playbackMode: The playback mode, including normal order, reverse order, bounce order and reversed bounce order.
public func playbackMode(_ playbackMode: SDAnimatedImagePlaybackMode) -> AnimatedImage {
self.imageConfiguration.playbackMode = playbackMode
return self
}
}

// Completion Handler
Expand Down
6 changes: 5 additions & 1 deletion SDWebImageSwiftUI/Classes/ImagePlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ public final class ImagePlayer : ObservableObject {
/// Animation playback rate
public var playbackRate: Double = 1.0

/// Animation playback mode
public var playbackMode: SDAnimatedImagePlaybackMode = .normal

deinit {
player?.stopPlaying()
currentFrame = nil
Expand Down Expand Up @@ -71,10 +74,11 @@ public final class ImagePlayer : ObservableObject {
imagePlayer.maxBufferSize = maxBufferSize
}
if let customLoopCount = customLoopCount {
imagePlayer.totalLoopCount = UInt(customLoopCount)
imagePlayer.totalLoopCount = customLoopCount
}
imagePlayer.runLoopMode = runLoopMode
imagePlayer.playbackRate = playbackRate
imagePlayer.playbackMode = playbackMode

self.player = imagePlayer

Expand Down
14 changes: 14 additions & 0 deletions SDWebImageSwiftUI/Classes/ImageViewWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,20 @@ extension PlatformView {
self.leadingAnchor.constraint(equalTo: superview.leadingAnchor, constant: 0).isActive = true
self.trailingAnchor.constraint(equalTo: superview.trailingAnchor, constant: 0).isActive = true
}

/// Finding the HostingView for UIKit/AppKit View.
/// - Parameter entry: The entry platform view
/// - Returns: The hosting view.
func findHostingView() -> PlatformView? {
var superview = self.superview
while let s = superview {
if NSStringFromClass(type(of: s)).contains("HostingView") {
return s
}
superview = s.superview
}
return nil
}
}

#endif
7 changes: 7 additions & 0 deletions SDWebImageSwiftUI/Classes/WebImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,13 @@ extension WebImage {
self.imagePlayer.playbackRate = playbackRate
return self
}

/// Control the animation playback mode. Default is .normal
/// - Parameter playbackMode: The playback mode, including normal order, reverse order, bounce order and reversed bounce order.
public func playbackMode(_ playbackMode: SDAnimatedImagePlaybackMode) -> WebImage {
self.imagePlayer.playbackMode = playbackMode
return self
}
}

#if DEBUG
Expand Down