Update with the playbackMode support for `WebImage` and `AnimatedImage`

This commit is contained in:
DreamPiggy 2021-02-23 15:59:44 +08:00
parent a30a71acb5
commit 0b646a6286
5 changed files with 42 additions and 12 deletions

View File

@ -160,6 +160,7 @@ var body: some View {
// The initial value of binding should be true // The initial value of binding should be true
.customLoopCount(1) // Custom loop count .customLoopCount(1) // Custom loop count
.playbackRate(2.0) // Playback speed rate .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 // `WebImage` supports advanced control just like `AnimatedImage`, but without the progressive animation support
} }
``` ```

View File

@ -84,6 +84,7 @@ final class AnimatedImageConfiguration: ObservableObject {
var pausable: Bool? var pausable: Bool?
var purgeable: Bool? var purgeable: Bool?
var playbackRate: Double? var playbackRate: Double?
var playbackMode: SDAnimatedImagePlaybackMode?
// These configurations only useful for web image loading // These configurations only useful for web image loading
var indicator: SDWebImageIndicator? var indicator: SDWebImageIndicator?
var transition: SDWebImageTransition? var transition: SDWebImageTransition?
@ -253,7 +254,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
} else { } else {
// This is a hack because of iOS 13's SwiftUI bug, the @Published does not trigger another `updateUIView` call // 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) // 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 let _ = hostingView.window {
#if os(macOS) #if os(macOS)
hostingView.viewDidMoveToWindow() hostingView.viewDidMoveToWindow()
@ -542,17 +543,13 @@ public struct AnimatedImage : PlatformViewRepresentable {
} else { } else {
view.wrapped.playbackRate = 1.0 view.wrapped.playbackRate = 1.0
} }
}
// Playback Mode
private static func findHostingView(from entry: PlatformView) -> PlatformView? { if let playbackMode = imageConfiguration.playbackMode {
var superview = entry.superview view.wrapped.playbackMode = playbackMode
while let s = superview { } else {
if NSStringFromClass(type(of: s)).contains("HostingView") { view.wrapped.playbackMode = .normal
return s
}
superview = s.superview
} }
return nil
} }
} }
@ -717,6 +714,13 @@ extension AnimatedImage {
self.imageConfiguration.playbackRate = playbackRate self.imageConfiguration.playbackRate = playbackRate
return self 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 // Completion Handler

View File

@ -26,6 +26,9 @@ public final class ImagePlayer : ObservableObject {
/// Animation playback rate /// Animation playback rate
public var playbackRate: Double = 1.0 public var playbackRate: Double = 1.0
/// Animation playback mode
public var playbackMode: SDAnimatedImagePlaybackMode = .normal
deinit { deinit {
player?.stopPlaying() player?.stopPlaying()
currentFrame = nil currentFrame = nil
@ -71,10 +74,11 @@ public final class ImagePlayer : ObservableObject {
imagePlayer.maxBufferSize = maxBufferSize imagePlayer.maxBufferSize = maxBufferSize
} }
if let customLoopCount = customLoopCount { if let customLoopCount = customLoopCount {
imagePlayer.totalLoopCount = UInt(customLoopCount) imagePlayer.totalLoopCount = customLoopCount
} }
imagePlayer.runLoopMode = runLoopMode imagePlayer.runLoopMode = runLoopMode
imagePlayer.playbackRate = playbackRate imagePlayer.playbackRate = playbackRate
imagePlayer.playbackMode = playbackMode
self.player = imagePlayer self.player = imagePlayer

View File

@ -114,6 +114,20 @@ extension PlatformView {
self.leadingAnchor.constraint(equalTo: superview.leadingAnchor, constant: 0).isActive = true self.leadingAnchor.constraint(equalTo: superview.leadingAnchor, constant: 0).isActive = true
self.trailingAnchor.constraint(equalTo: superview.trailingAnchor, 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 #endif

View File

@ -399,6 +399,13 @@ extension WebImage {
self.imagePlayer.playbackRate = playbackRate self.imagePlayer.playbackRate = playbackRate
return self 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 #if DEBUG