AFViewShaker.m 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. //
  2. // AFViewShaker
  3. // AFViewShaker
  4. //
  5. // Created by Philip Vasilchenko on 03.12.13.
  6. // Copyright (c) 2014 okolodev. All rights reserved.
  7. //
  8. #import "AFViewShaker.h"
  9. static NSTimeInterval const kAFViewShakerDefaultDuration = 0.5;
  10. static NSString * const kAFViewShakerAnimationKey = @"kAFViewShakerAnimationKey";
  11. @interface AFViewShaker ()
  12. @property (nonatomic, strong) NSArray * views;
  13. @property (nonatomic, assign) NSUInteger completedAnimations;
  14. @property (nonatomic, copy) void (^completionBlock)();
  15. @end
  16. @implementation AFViewShaker
  17. - (instancetype)initWithView:(UIView *)view {
  18. return [self initWithViewsArray:@[ view ]];
  19. }
  20. - (instancetype)initWithViewsArray:(NSArray *)viewsArray {
  21. self = [super init];
  22. if ( self ) {
  23. self.views = viewsArray;
  24. }
  25. return self;
  26. }
  27. #pragma mark - Public methods
  28. - (void)shake {
  29. [self shakeWithDuration:kAFViewShakerDefaultDuration completion:nil];
  30. }
  31. - (void)shakeWithDuration:(NSTimeInterval)duration completion:(void (^)())completion {
  32. self.completionBlock = completion;
  33. for (UIView * view in self.views) {
  34. [self addShakeAnimationForView:view withDuration:duration];
  35. }
  36. }
  37. #pragma mark - Shake Animation
  38. - (void)addShakeAnimationForView:(UIView *)view withDuration:(NSTimeInterval)duration {
  39. CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.x"];
  40. CGFloat currentTx = view.transform.tx;
  41. animation.delegate = self;
  42. animation.duration = duration;
  43. animation.values = @[ @(currentTx), @(currentTx + 10), @(currentTx-8), @(currentTx + 8), @(currentTx -5), @(currentTx + 5), @(currentTx) ];
  44. animation.keyTimes = @[ @(0), @(0.225), @(0.425), @(0.6), @(0.75), @(0.875), @(1) ];
  45. animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
  46. [view.layer addAnimation:animation forKey:kAFViewShakerAnimationKey];
  47. }
  48. #pragma mark - CAAnimation Delegate
  49. - (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag {
  50. self.completedAnimations += 1;
  51. if ( self.completedAnimations >= self.views.count ) {
  52. self.completedAnimations = 0;
  53. if ( self.completionBlock ) {
  54. self.completionBlock();
  55. }
  56. }
  57. }
  58. @end