/* * Copyright (c) 2010-2020 Belledonne Communications SARL. * * This file is part of linphone-iphone * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import "UIBouncingView.h" #import "CAAnimation+Blocks.h" #import "Utils.h" static NSString *const kBounceAnimation = @"bounce"; static NSString *const kAppearAnimation = @"appear"; static NSString *const kDisappearAnimation = @"disappear"; @implementation UIBouncingView INIT_WITH_COMMON_CF { [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(settingsUpdate:) name:kLinphoneSettingsUpdate object:nil]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; return self; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } - (void)settingsUpdate:(NSNotification *)notif { if (ANIMATED == false) { [self stopAnimating:NO]; } else { if (![self isHidden]) { self.hidden = YES; [self startAnimating:YES]; } } } - (void)applicationWillEnterForeground:(NSNotification *)notif { // Force the animations if (self.isHidden) { self.hidden = NO; [self stopAnimating:NO]; } else { self.hidden = YES; [self startAnimating:NO]; } } #pragma mark - Animation - (void)appearAnimation:(NSString *)animationID target:(UIView *)target completion:(void (^)(BOOL finished))completion { CABasicAnimation *appear = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; appear.duration = 0.4; appear.fromValue = [NSNumber numberWithDouble:0.0f]; appear.toValue = [NSNumber numberWithDouble:1.0f]; appear.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; appear.fillMode = kCAFillModeForwards; appear.removedOnCompletion = NO; [appear setCompletion:completion]; [target.layer addAnimation:appear forKey:animationID]; } - (void)disappearAnimation:(NSString *)animationID target:(UIView *)target completion:(void (^)(BOOL finished))completion { CABasicAnimation *disappear = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; disappear.duration = 0.4; disappear.fromValue = [NSNumber numberWithDouble:1.0f]; disappear.toValue = [NSNumber numberWithDouble:0.0f]; disappear.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; disappear.fillMode = kCAFillModeForwards; disappear.removedOnCompletion = NO; [disappear setCompletion:completion]; [target.layer addAnimation:disappear forKey:animationID]; } - (void)startBounceAnimation:(NSString *)animationID target:(UIView *)target { CABasicAnimation *bounce = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"]; bounce.duration = 0.3; bounce.fromValue = [NSNumber numberWithDouble:0.0f]; bounce.toValue = [NSNumber numberWithDouble:8.0f]; bounce.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; bounce.autoreverses = TRUE; bounce.repeatCount = HUGE_VALF; [target.layer addAnimation:bounce forKey:animationID]; } - (void)stopBounceAnimation:(NSString *)animationID target:(UIView *)target { [target.layer removeAnimationForKey:animationID]; } - (void)startAnimating:(BOOL)animated { animated = NO; if (!self.hidden) { return; } [self setHidden:FALSE]; if (ANIMATED) { if (animated) { [self appearAnimation:kAppearAnimation target:self completion:^(BOOL finished) { [self startBounceAnimation:kBounceAnimation target:self]; if (finished) { [self.layer removeAnimationForKey:kAppearAnimation]; } }]; } else { [self startBounceAnimation:kBounceAnimation target:self]; } } } - (void)stopAnimating:(BOOL)animated { animated = NO; if (self.hidden) { return; } [self stopBounceAnimation:kBounceAnimation target:self]; if (animated) { [self disappearAnimation:kDisappearAnimation target:self completion:^(BOOL finished) { [self setHidden:TRUE]; if (finished) { [self.layer removeAnimationForKey:kDisappearAnimation]; } }]; } else { [self setHidden:TRUE]; } } @end