16
16
17
17
#pragma mark - SPI
18
18
19
+ #define kCGImageAnimationStatus_Uninitialized -1
20
+
19
21
@protocol CALayerProtocol <NSObject >
20
22
@property (nullable , strong ) id contents;
21
23
@property CGFloat contentsScale;
@@ -24,6 +26,13 @@ @protocol CALayerProtocol <NSObject>
24
26
@protocol UIViewProtocol <NSObject >
25
27
@property (nonatomic , strong , readonly ) id <CALayerProtocol> layer;
26
28
@property (nonatomic , assign ) SDImageScaleMode contentMode;
29
+ @property (nonatomic , readonly ) id <UIViewProtocol> superview;
30
+ @property (nonatomic , readonly , copy ) NSArray <id<UIViewProtocol>> *subviews;
31
+ @property (nonatomic , readonly ) id window;
32
+ @property (nonatomic ) CGFloat alpha;
33
+ @property (nonatomic , getter =isHidden) BOOL hidden;
34
+ @property (nonatomic , getter =isOpaque) BOOL opaque;
35
+
27
36
@end
28
37
29
38
@interface WKInterfaceObject ()
@@ -44,6 +53,14 @@ @interface SDAnimatedImageStatus : NSObject
44
53
45
54
@implementation SDAnimatedImageStatus
46
55
56
+ - (instancetype )init {
57
+ self = [super init ];
58
+ if (self) {
59
+ _animationStatus = kCGImageAnimationStatus_Uninitialized ;
60
+ }
61
+ return self;
62
+ }
63
+
47
64
@end
48
65
49
66
@interface SDAnimatedImageInterface () {
@@ -59,6 +76,8 @@ @interface SDAnimatedImageInterface () {
59
76
@property (nonatomic , assign ) CGFloat animatedImageScale;
60
77
@property (nonatomic , strong ) SDAnimatedImageStatus *currentStatus;
61
78
@property (nonatomic , strong ) NSNumber *animationRepeatCount;
79
+ @property (nonatomic , assign , getter =isAnimatedFormat) BOOL animatedFormat;
80
+ @property (nonatomic , assign , getter =isAnimating) BOOL animating;
62
81
63
82
@end
64
83
@@ -105,6 +124,8 @@ - (void)setImage:(UIImage *)image {
105
124
}
106
125
_image = image;
107
126
127
+ // Stop animating
128
+ [self stopBuiltInAnimation ];
108
129
// Reset all value
109
130
[self resetAnimatedImage ];
110
131
@@ -126,15 +147,29 @@ - (void)setImage:(UIImage *)image {
126
147
NSData *animatedImageData = animatedImage.animatedImageData ;
127
148
SDImageFormat format = [NSData sd_imageFormatForImageData: animatedImageData];
128
149
if (format == SDImageFormatGIF || format == SDImageFormatPNG) {
129
- [self startBuiltInAnimationWithImage: animatedImage];
150
+ self.animatedFormat = YES ;
151
+ [self startBuiltInAnimation ];
152
+ } else {
153
+ self.animatedFormat = NO ;
154
+ [self stopBuiltInAnimation ];
130
155
}
131
-
132
- // Update should animate
133
- [self updateShouldAnimate ];
134
156
}
135
157
}
136
158
137
- - (void )startBuiltInAnimationWithImage : (UIImage<SDAnimatedImage> *)animatedImage {
159
+ - (void )updateAnimation {
160
+ [self updateShouldAnimate ];
161
+ if (self.currentStatus .shouldAnimate ) {
162
+ [self startBuiltInAnimation ];
163
+ } else {
164
+ [self stopBuiltInAnimation ];
165
+ }
166
+ }
167
+
168
+ - (void )startBuiltInAnimation {
169
+ if (self.currentStatus && self.currentStatus .animationStatus == 0 ) {
170
+ return ;
171
+ }
172
+ UIImage<SDAnimatedImage> *animatedImage = self.animatedImage ;
138
173
NSData *animatedImageData = animatedImage.animatedImageData ;
139
174
NSUInteger maxLoopCount;
140
175
if (self.animationRepeatCount != nil ) {
@@ -148,7 +183,7 @@ - (void)startBuiltInAnimationWithImage:(UIImage<SDAnimatedImage> *)animatedImage
148
183
maxLoopCount = ((__bridge NSNumber *)kCFNumberPositiveInfinity ).unsignedIntegerValue - 1 ;
149
184
}
150
185
NSDictionary *options = @{(__bridge NSString *)kCGImageAnimationLoopCount : @(maxLoopCount)};
151
- SDAnimatedImageStatus *status = [SDAnimatedImageStatus new ];
186
+ SDAnimatedImageStatus *status = [[ SDAnimatedImageStatus alloc ] init ];
152
187
status.shouldAnimate = YES ;
153
188
__weak typeof (self) wself = self;
154
189
status.animationStatus = CGAnimateImageDataWithBlock ((__bridge CFDataRef)animatedImageData, (__bridge CFDictionaryRef)options, ^(size_t index, CGImageRef _Nonnull imageRef, bool * _Nonnull stop) {
@@ -171,6 +206,11 @@ - (void)startBuiltInAnimationWithImage:(UIImage<SDAnimatedImage> *)animatedImage
171
206
self.currentStatus = status;
172
207
}
173
208
209
+ - (void )stopBuiltInAnimation {
210
+ self.currentStatus .shouldAnimate = NO ;
211
+ self.currentStatus .animationStatus = kCGImageAnimationStatus_Uninitialized ;
212
+ }
213
+
174
214
- (void )displayLayer {
175
215
if (self.currentFrame ) {
176
216
id <CALayerProtocol> layer = [self _interfaceView ].layer ;
@@ -184,44 +224,43 @@ - (void)resetAnimatedImage
184
224
self.animatedImage = nil ;
185
225
self.totalFrameCount = 0 ;
186
226
self.totalLoopCount = 0 ;
187
- // reset current state
188
- self.currentStatus .shouldAnimate = NO ;
189
- self.currentStatus = nil ;
190
- [self resetCurrentFrameIndex ];
191
- self.animatedImageScale = 1 ;
192
- }
193
-
194
- - (void )resetCurrentFrameIndex
195
- {
196
227
self.currentFrame = nil ;
197
228
self.currentFrameIndex = 0 ;
198
229
self.currentLoopCount = 0 ;
230
+ self.animatedImageScale = 1 ;
231
+ self.animatedFormat = NO ;
232
+ self.currentStatus = nil ;
199
233
}
200
234
201
235
- (void )updateShouldAnimate
202
236
{
203
- self.currentStatus .shouldAnimate = self.animatedImage && self.totalFrameCount > 1 ;
237
+ id <UIViewProtocol> view = [self _interfaceView ];
238
+ BOOL isVisible = view.window && view.superview && ![view isHidden ] && view.alpha > 0.0 ;
239
+ self.currentStatus .shouldAnimate = self.animatedImage && self.totalFrameCount > 1 && self.isAnimatedFormat && isVisible;
204
240
}
205
241
206
242
- (void )startAnimating {
243
+ self.animating = YES ;
207
244
if (self.animatedImage ) {
208
- self. currentStatus . shouldAnimate = YES ;
245
+ [ self startBuiltInAnimation ] ;
209
246
} else if (_image.images .count > 0 ) {
210
247
[super startAnimating ];
211
248
}
212
249
}
213
250
214
251
- (void )startAnimatingWithImagesInRange : (NSRange )imageRange duration : (NSTimeInterval )duration repeatCount : (NSInteger )repeatCount {
252
+ self.animating = YES ;
215
253
if (self.animatedImage ) {
216
- self. currentStatus . shouldAnimate = YES ;
254
+ [ self startBuiltInAnimation ] ;
217
255
} else if (_image.images .count > 0 ) {
218
256
[super startAnimatingWithImagesInRange: imageRange duration: duration repeatCount: repeatCount];
219
257
}
220
258
}
221
259
222
260
- (void )stopAnimating {
261
+ self.animating = NO ;
223
262
if (self.animatedImage ) {
224
- self. currentStatus . shouldAnimate = NO ;
263
+ [ self stopBuiltInAnimation ] ;
225
264
} else if (_image.images .count > 0 ) {
226
265
[super stopAnimating ];
227
266
}
0 commit comments