Merge pull request #14 from SDWebImage/feature_animatedimage_animating_control

Supports AnimatedImage animation control using of SwiftUI Binding
This commit is contained in:
DreamPiggy 2019-10-05 15:54:55 +08:00 committed by GitHub
commit df7728d894
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 28 deletions

View File

@ -13,6 +13,7 @@ struct DetailView: View {
let url: String
let animated: Bool
@State var progress: CGFloat = 1
@State var isAnimating: Bool = true
var body: some View {
VStack {
@ -24,7 +25,7 @@ struct DetailView: View {
Spacer()
HStack {
if animated {
AnimatedImage(url: URL(string:url), options: [.progressiveLoad])
AnimatedImage(url: URL(string:url), options: [.progressiveLoad], isAnimating: $isAnimating)
.onProgress(perform: { (receivedSize, expectedSize) in
// SwiftUI engine itself ensure the main queue dispatch
if (expectedSize >= 0) {
@ -35,6 +36,9 @@ struct DetailView: View {
})
.resizable()
.scaledToFit()
.navigationBarItems(trailing: Button(isAnimating ? "Stop" : "Start") {
self.isAnimating.toggle()
})
} else {
WebImage(url: URL(string:url), options: [.progressiveLoad])
.onProgress(perform: { (receivedSize, expectedSize) in

View File

@ -85,20 +85,24 @@ var body: some View {
```swift
var body: some View {
Group {
AnimatedImage(url: URL(string: "https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif")) // Network
// Network
AnimatedImage(url: URL(string: "https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif"))
.onFailure(perform: { (error) in
// Error
})
.scaledToFit()
AnimatedImage(data: try! Data(contentsOf: URL(fileURLWithPath: "/tmp/foo.webp"))) // Data
// Data
AnimatedImage(data: try! Data(contentsOf: URL(fileURLWithPath: "/tmp/foo.webp")))
.customLoopCount(1)
AnimatedImage(name: "animation1") // Bundle (not Asset Catalog)
// Bundle (not Asset Catalog)
AnimatedImage(name: "animation1", isAnimating: $isAnimating)) // Animation control binding
.maxBufferSize(.max)
}
}
```
- [x] Supports network image as well as local data and bundle image
- [x] Supports animation control using the SwiftUI Binding
- [x] Supports advanced control like loop count, incremental load, buffer size.
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.

View File

@ -48,6 +48,46 @@ public struct AnimatedImage : PlatformViewRepresentable {
var webOptions: SDWebImageOptions = []
var webContext: [SDWebImageContextOption : Any]? = nil
/// A Binding to control the animation. You can bind external logic to control the animation status.
/// True to start animation, false to stop animation.
@Binding public var isAnimating: Bool
public init(url: URL?, placeholder: PlatformImage? = nil, options: SDWebImageOptions = [], context: [SDWebImageContextOption : Any]? = nil) {
self.init(url: url, placeholder: placeholder, options: options, context: context, isAnimating: .constant(true))
}
public init(url: URL?, placeholder: PlatformImage? = nil, options: SDWebImageOptions = [], context: [SDWebImageContextOption : Any]? = nil, isAnimating: Binding<Bool>) {
self._isAnimating = isAnimating
self.placeholder = placeholder
self.webOptions = options
self.webContext = context
self.imageModel.url = url
}
public init(name: String, bundle: Bundle? = nil) {
self.init(name: name, bundle: bundle, isAnimating: .constant(true))
}
public init(name: String, bundle: Bundle? = nil, isAnimating: Binding<Bool>) {
self._isAnimating = isAnimating
#if os(macOS)
let image = SDAnimatedImage(named: name, in: bundle)
#else
let image = SDAnimatedImage(named: name, in: bundle, compatibleWith: nil)
#endif
self.imageModel.image = image
}
public init(data: Data, scale: CGFloat = 0) {
self.init(data: data, scale: scale, isAnimating: .constant(true))
}
public init(data: Data, scale: CGFloat = 0, isAnimating: Binding<Bool>) {
self._isAnimating = isAnimating
let image = SDAnimatedImage(data: data, scale: scale)
self.imageModel.image = image
}
#if os(macOS)
public typealias NSViewType = AnimatedImageViewWrapper
#else
@ -90,6 +130,20 @@ public struct AnimatedImage : PlatformViewRepresentable {
}
}
#if os(macOS)
if self.isAnimating != view.wrapped.animates {
view.wrapped.animates = self.isAnimating
}
#else
if self.isAnimating != view.wrapped.isAnimating {
if self.isAnimating {
view.wrapped.startAnimating()
} else {
view.wrapped.stopAnimating()
}
}
#endif
configureView(view, context: context)
layoutView(view, context: context)
}
@ -310,30 +364,6 @@ extension AnimatedImage {
}
}
// Initializer
extension AnimatedImage {
public init(url: URL?, placeholder: PlatformImage? = nil, options: SDWebImageOptions = [], context: [SDWebImageContextOption : Any]? = nil) {
self.placeholder = placeholder
self.webOptions = options
self.webContext = context
self.imageModel.url = url
}
public init(name: String, bundle: Bundle? = nil) {
#if os(macOS)
let image = SDAnimatedImage(named: name, in: bundle)
#else
let image = SDAnimatedImage(named: name, in: bundle, compatibleWith: nil)
#endif
self.imageModel.image = image
}
public init(data: Data, scale: CGFloat = 0) {
let image = SDAnimatedImage(data: data, scale: scale)
self.imageModel.image = image
}
}
#if DEBUG
struct AnimatedImage_Previews : PreviewProvider {
static var previews: some View {