Created
August 14, 2018 20:10
-
-
Save DreamingInBinary/a4a2d5183b8b9a093ef9f682028653c9 to your computer and use it in GitHub Desktop.
Revisions
-
Jordan Morgan created this gist
Aug 14, 2018 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,115 @@ // // UIView+BFRShimmer.h // BFRUtils // // Created by Jordan Morgan on 8/14/18. // Copyright © 2018 Buffer. All rights reserved. // #import <UIKit/UIKit.h> NS_ASSUME_NONNULL_BEGIN @interface UIView (BFRShimmer) @property (strong, nonatomic, readonly, nonnull) CAGradientLayer *gradient; @property (strong, nonatomic, readonly, nonnull) CABasicAnimation *shimmerAnimation; - (void)startShimmering; - (void)startShimmeringWithRepitions:(NSInteger)reps; - (void)endShimmering; @end NS_ASSUME_NONNULL_END // // UIView+BFRShimmer.m // BFRUtils // // Created by Jordan Morgan on 8/14/18. // Copyright © 2018 Buffer. All rights reserved. // #import "UIView+BFRShimmer.h" #import <objc/runtime.h> static NSString * const BFR_SHIMMER_KEY = @"bfr.Shimmering.animationKey"; @implementation UIView (BFRShimmer) #pragma mark - Dynamic Properties static const void *GradientKey = &GradientKey; static const void *AnimationKey = &AnimationKey; - (CAGradientLayer *)gradient { CAGradientLayer *returnVal = objc_getAssociatedObject(self, GradientKey); if (!returnVal) { returnVal = [CAGradientLayer new]; objc_setAssociatedObject(self, GradientKey, returnVal, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return returnVal; } - (CABasicAnimation *)shimmerAnimation { CABasicAnimation *returnVal = objc_getAssociatedObject(self, AnimationKey); if (!returnVal) { returnVal = [CABasicAnimation animationWithKeyPath:@"position"]; objc_setAssociatedObject(self, AnimationKey, returnVal, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } return returnVal; } #pragma mark - Public API - (void)startShimmeringWithRepitions:(NSInteger)reps { [CATransaction begin]; [CATransaction setCompletionBlock:^{ [self endShimmering]; }]; UIColor *lightColor = [[UIColor whiteColor] colorWithAlphaComponent:0.1]; UIColor *darkColor = [[UIColor blackColor] colorWithAlphaComponent:1.0]; CGFloat length = CGRectGetWidth(self.layer.bounds); CGFloat extraDistance = length + 1.0f * 0.4f; CGFloat fullShimmerLength = length * 3.0f + extraDistance; CGFloat travelDistance = length * 2.0f + extraDistance; CGFloat highlightOutsideLength = 0.0 / 2.0; CGFloat startPoint = (length + extraDistance) / fullShimmerLength; CGFloat endPoint = travelDistance / fullShimmerLength; self.gradient.bounds = CGRectMake(0.0, 0.0, fullShimmerLength, CGRectGetHeight(self.layer.bounds)); self.gradient.position = CGPointMake(-travelDistance, 0.0); self.gradient.anchorPoint = CGPointZero; self.gradient.startPoint = CGPointMake(startPoint, 0.0); self.gradient.endPoint = CGPointMake(endPoint, 0.0); self.gradient.locations = @[@(highlightOutsideLength), @(0.5), @(1.0 - highlightOutsideLength)]; self.gradient.colors = @[(id)darkColor.CGColor, (id)lightColor.CGColor, (id)darkColor.CGColor]; self.shimmerAnimation.duration = 1.0; self.shimmerAnimation.repeatCount = reps > 0 ? reps : INFINITY; self.shimmerAnimation.toValue = [NSValue valueWithCGPoint:CGPointZero]; [self.gradient addAnimation:self.shimmerAnimation forKey:BFR_SHIMMER_KEY]; self.layer.mask = self.gradient; [CATransaction commit]; } - (void)startShimmering { [self startShimmeringWithRepitions:0]; } - (void)endShimmering { [self.layer.mask removeAnimationForKey:BFR_SHIMMER_KEY]; self.layer.mask = nil; [self.layer setNeedsDisplay]; } @end