Created
June 12, 2014 15:02
-
-
Save zats/1a3fe941251b4a32b531 to your computer and use it in GitHub Desktop.
Enabling UIImageRenderingModeAlwaysTemplate for UIImageView
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static NSString *const WMLTemplatedAnimationColorFillLayerName = @"WMLTemplatedAnimationFillLayerName"; | |
static NSString *const WMLTemplatedAnimationMaskLayerName = @"WMLTemplatedAnimationMaskLayerName"; | |
@interface UIImageView (WMLTemplatedAnimation) | |
- (void)wml_startAnimating; | |
- (void)wml_stopAnimating; | |
@end | |
@implementation UIImageView (WMLTemplatedAnimation) | |
- (void)wml_startAnimating { | |
if ([self isAnimating]) { | |
return; | |
} | |
NSArray *animationImages = [self isHighlighted] && self.highlightedAnimationImages ? self.highlightedAnimationImages : self.animationImages; | |
UIImage *probeImage = [animationImages firstObject]; | |
if (probeImage.renderingMode != UIImageRenderingModeAlwaysTemplate) { | |
[self startAnimating]; | |
return; | |
} | |
CGSize imageSize = probeImage.size; | |
self.frame = ({ | |
CGRect frame = self.frame; | |
frame.size = imageSize; | |
frame; | |
}); | |
NSMutableArray *cgAnimationImages = [NSMutableArray arrayWithCapacity:[animationImages count]]; | |
for (UIImage *image in animationImages) { | |
[cgAnimationImages addObject:(__bridge id)[image CGImage]]; | |
} | |
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation]; | |
animation.keyPath = @"contents"; | |
animation.values = cgAnimationImages; | |
animation.calculationMode = kCAAnimationDiscrete; | |
animation.duration = self.animationDuration ?: 1.633; | |
animation.repeatCount = self.animationRepeatCount != 0 ?: HUGE_VALF; | |
animation.removedOnCompletion = self.animationRepeatCount < 1; | |
animation.delegate = [self valueForKey:@"_storage"]; | |
self.layer.contents = nil; | |
CALayer *tintColorLayer = [self wml_layerForName:WMLTemplatedAnimationColorFillLayerName]; | |
if (!tintColorLayer) { | |
tintColorLayer = [CALayer layer]; | |
tintColorLayer.name = WMLTemplatedAnimationColorFillLayerName; | |
tintColorLayer.frame = self.layer.bounds; | |
tintColorLayer.transform = self.layer.transform; | |
tintColorLayer.contents = nil; | |
} | |
tintColorLayer.backgroundColor = [self.tintColor CGColor]; | |
CALayer *mask = [self wml_layerForName:WMLTemplatedAnimationMaskLayerName]; | |
if (!mask) { | |
mask = [CALayer layer]; | |
mask.name = WMLTemplatedAnimationMaskLayerName; | |
mask.frame = self.layer.bounds; | |
mask.transform = self.layer.transform; | |
tintColorLayer.mask = mask; | |
} | |
[mask addAnimation:animation forKey:@"contents"]; | |
[self.layer addSublayer:tintColorLayer]; | |
// TODO: this triggers regular startAnimating | |
[self setValue:@YES forKey:@"animating"]; | |
} | |
- (void)wml_stopAnimating { | |
if (![self isAnimating]) { | |
return; | |
} | |
CALayer *colorFillLayer = [self wml_layerForName:WMLTemplatedAnimationColorFillLayerName]; | |
[colorFillLayer removeFromSuperlayer]; | |
[self stopAnimating]; | |
} | |
- (CALayer *)wml_layerForName:(NSString *)name { | |
for (CALayer *layer in self.layer.sublayers) { | |
if ([layer.name isEqualToString:name]) { | |
return layer; | |
} | |
} | |
return nil; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I hit a wall trying to find a solve for this exact problem... your's worked perfectly - thanks a bunch!