Skip to content

Commit df7728d

Browse files
authored
Merge pull request #14 from SDWebImage/feature_animatedimage_animating_control
Supports AnimatedImage animation control using of SwiftUI Binding
2 parents d23f9b4 + bcb871a commit df7728d

File tree

3 files changed

+66
-28
lines changed

3 files changed

+66
-28
lines changed

Example/SDWebImageSwiftUIDemo/DetailView.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ struct DetailView: View {
1313
let url: String
1414
let animated: Bool
1515
@State var progress: CGFloat = 1
16+
@State var isAnimating: Bool = true
1617

1718
var body: some View {
1819
VStack {
@@ -24,7 +25,7 @@ struct DetailView: View {
2425
Spacer()
2526
HStack {
2627
if animated {
27-
AnimatedImage(url: URL(string:url), options: [.progressiveLoad])
28+
AnimatedImage(url: URL(string:url), options: [.progressiveLoad], isAnimating: $isAnimating)
2829
.onProgress(perform: { (receivedSize, expectedSize) in
2930
// SwiftUI engine itself ensure the main queue dispatch
3031
if (expectedSize >= 0) {
@@ -35,6 +36,9 @@ struct DetailView: View {
3536
})
3637
.resizable()
3738
.scaledToFit()
39+
.navigationBarItems(trailing: Button(isAnimating ? "Stop" : "Start") {
40+
self.isAnimating.toggle()
41+
})
3842
} else {
3943
WebImage(url: URL(string:url), options: [.progressiveLoad])
4044
.onProgress(perform: { (receivedSize, expectedSize) in

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,24 @@ var body: some View {
8585
```swift
8686
var body: some View {
8787
Group {
88-
AnimatedImage(url: URL(string: "https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif")) // Network
88+
// Network
89+
AnimatedImage(url: URL(string: "https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif"))
8990
.onFailure(perform: { (error) in
9091
// Error
9192
})
9293
.scaledToFit()
93-
AnimatedImage(data: try! Data(contentsOf: URL(fileURLWithPath: "/tmp/foo.webp"))) // Data
94+
// Data
95+
AnimatedImage(data: try! Data(contentsOf: URL(fileURLWithPath: "/tmp/foo.webp")))
9496
.customLoopCount(1)
95-
AnimatedImage(name: "animation1") // Bundle (not Asset Catalog)
97+
// Bundle (not Asset Catalog)
98+
AnimatedImage(name: "animation1", isAnimating: $isAnimating)) // Animation control binding
9699
.maxBufferSize(.max)
97100
}
98101
}
99102
```
100103

101104
- [x] Supports network image as well as local data and bundle image
105+
- [x] Supports animation control using the SwiftUI Binding
102106
- [x] Supports advanced control like loop count, incremental load, buffer size.
103107

104108
Note: `AnimatedImage` supports both image url or image data for animated image format. Which use the SDWebImage's [Animated ImageView](https://github.com/SDWebImage/SDWebImage/wiki/Advanced-Usage#animated-image-50) for internal implementation.

SDWebImageSwiftUI/Classes/AnimatedImage.swift

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,46 @@ public struct AnimatedImage : PlatformViewRepresentable {
4848
var webOptions: SDWebImageOptions = []
4949
var webContext: [SDWebImageContextOption : Any]? = nil
5050

51+
/// A Binding to control the animation. You can bind external logic to control the animation status.
52+
/// True to start animation, false to stop animation.
53+
@Binding public var isAnimating: Bool
54+
55+
public init(url: URL?, placeholder: PlatformImage? = nil, options: SDWebImageOptions = [], context: [SDWebImageContextOption : Any]? = nil) {
56+
self.init(url: url, placeholder: placeholder, options: options, context: context, isAnimating: .constant(true))
57+
}
58+
59+
public init(url: URL?, placeholder: PlatformImage? = nil, options: SDWebImageOptions = [], context: [SDWebImageContextOption : Any]? = nil, isAnimating: Binding<Bool>) {
60+
self._isAnimating = isAnimating
61+
self.placeholder = placeholder
62+
self.webOptions = options
63+
self.webContext = context
64+
self.imageModel.url = url
65+
}
66+
67+
public init(name: String, bundle: Bundle? = nil) {
68+
self.init(name: name, bundle: bundle, isAnimating: .constant(true))
69+
}
70+
71+
public init(name: String, bundle: Bundle? = nil, isAnimating: Binding<Bool>) {
72+
self._isAnimating = isAnimating
73+
#if os(macOS)
74+
let image = SDAnimatedImage(named: name, in: bundle)
75+
#else
76+
let image = SDAnimatedImage(named: name, in: bundle, compatibleWith: nil)
77+
#endif
78+
self.imageModel.image = image
79+
}
80+
81+
public init(data: Data, scale: CGFloat = 0) {
82+
self.init(data: data, scale: scale, isAnimating: .constant(true))
83+
}
84+
85+
public init(data: Data, scale: CGFloat = 0, isAnimating: Binding<Bool>) {
86+
self._isAnimating = isAnimating
87+
let image = SDAnimatedImage(data: data, scale: scale)
88+
self.imageModel.image = image
89+
}
90+
5191
#if os(macOS)
5292
public typealias NSViewType = AnimatedImageViewWrapper
5393
#else
@@ -90,6 +130,20 @@ public struct AnimatedImage : PlatformViewRepresentable {
90130
}
91131
}
92132

133+
#if os(macOS)
134+
if self.isAnimating != view.wrapped.animates {
135+
view.wrapped.animates = self.isAnimating
136+
}
137+
#else
138+
if self.isAnimating != view.wrapped.isAnimating {
139+
if self.isAnimating {
140+
view.wrapped.startAnimating()
141+
} else {
142+
view.wrapped.stopAnimating()
143+
}
144+
}
145+
#endif
146+
93147
configureView(view, context: context)
94148
layoutView(view, context: context)
95149
}
@@ -310,30 +364,6 @@ extension AnimatedImage {
310364
}
311365
}
312366

313-
// Initializer
314-
extension AnimatedImage {
315-
public init(url: URL?, placeholder: PlatformImage? = nil, options: SDWebImageOptions = [], context: [SDWebImageContextOption : Any]? = nil) {
316-
self.placeholder = placeholder
317-
self.webOptions = options
318-
self.webContext = context
319-
self.imageModel.url = url
320-
}
321-
322-
public init(name: String, bundle: Bundle? = nil) {
323-
#if os(macOS)
324-
let image = SDAnimatedImage(named: name, in: bundle)
325-
#else
326-
let image = SDAnimatedImage(named: name, in: bundle, compatibleWith: nil)
327-
#endif
328-
self.imageModel.image = image
329-
}
330-
331-
public init(data: Data, scale: CGFloat = 0) {
332-
let image = SDAnimatedImage(data: data, scale: scale)
333-
self.imageModel.image = image
334-
}
335-
}
336-
337367
#if DEBUG
338368
struct AnimatedImage_Previews : PreviewProvider {
339369
static var previews: some View {

0 commit comments

Comments
 (0)