Last active
May 31, 2022 17:51
-
-
Save SergLam/491e156099c67004c517a1add784c776 to your computer and use it in GitHub Desktop.
UIView animation with CABasicAnimation - border width and color
This file contains 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 const CGFloat kCornerRadiusStateNormal = 20.0f; | |
static const CGFloat kCornerRadiusStateSelected = 40.0f; | |
static const CGFloat kBorderWidth = 3.0f; | |
// First variant, long and ugly | |
- (void)updateStateAnimated:(BOOL)animated { | |
if (animated) { | |
CAMediaTimingFunction* timing =[[CAMediaTimingFunction alloc] initWithControlPoints:0.2f:0.0f:0.0f:1.0f]; | |
[CATransaction begin]; | |
[CATransaction setAnimationDuration:kAnimationDuration]; | |
[CATransaction setAnimationTimingFunction:timing]; | |
CGFloat fromCornerRadius = self.isSelected ? kCornerRadiusStateNormal : kCornerRadiusStateSelected; | |
CGFloat toCornerRadius = self.isSelected ? kCornerRadiusStateSelected : kCornerRadiusStateNormal; | |
CABasicAnimation* cornerRadiusAnimation = [CABasicAnimation animationWithKeyPath:@"cornerRadius"]; | |
cornerRadiusAnimation.removedOnCompletion = NO; | |
cornerRadiusAnimation.timingFunction = timing; | |
cornerRadiusAnimation.fromValue = [NSNumber numberWithFloat:fromCornerRadius]; | |
cornerRadiusAnimation.toValue = [NSNumber numberWithFloat:toCornerRadius]; | |
cornerRadiusAnimation.duration = kAnimationDuration; | |
CGFloat fromBorderWidth = self.isSelected ? kBorderWidth : 0; | |
CGFloat toBorderWidth = self.isSelected ? 0 : kBorderWidth; | |
CABasicAnimation* borderWidthAnimation = [CABasicAnimation animationWithKeyPath:@"borderWidth"]; | |
borderWidthAnimation.removedOnCompletion = NO; | |
borderWidthAnimation.timingFunction = timing; | |
borderWidthAnimation.fromValue = [NSNumber numberWithFloat:fromBorderWidth]; | |
borderWidthAnimation.toValue = [NSNumber numberWithFloat:toBorderWidth]; | |
borderWidthAnimation.duration = kAnimationDuration; | |
CAAnimationGroup *group = [[CAAnimationGroup alloc] init]; | |
group.animations = @[ cornerRadiusAnimation, borderWidthAnimation]; | |
group.duration = kAnimationDuration; | |
group.beginTime = 0.0f; | |
__weak __typeof__(self) weakSelf = self; | |
[CATransaction setCompletionBlock:^{ | |
weakSelf.layer.borderWidth = toBorderWidth; | |
weakSelf.layer.cornerRadius = toCornerRadius; | |
}]; | |
[self.layer addAnimation:group forKey:@"tileAnimation"]; | |
[CATransaction commit]; | |
} else { | |
self.layer.cornerRadius = self.isSelected ? kCornerRadiusStateSelected : kCornerRadiusStateNormal; | |
self.layer.borderWidth = self.isSelected ? 0 : kBorderWidth; | |
} | |
} | |
// Second variant, short and sexy | |
- (void)updateStateAnimated:(BOOL)animated { | |
__weak __typeof__(self) weakSelf = self; | |
void (^animationsBlock)(void) = ^{ | |
weakSelf.layer.cornerRadius = | |
weakSelf.isSelected ? kCornerRadiusStateSelected : kCornerRadiusStateNormal; | |
weakSelf.layer.borderWidth = | |
[weakSelf isBorderHiddenForState:weakSelf.state] ? 0 : kBorderWidth; | |
}; | |
if (!animated) { | |
animationsBlock(); | |
return; | |
} | |
[CATransaction begin]; | |
[CATransaction setAnimationDuration:kCornerRadiusAnimationDuration]; | |
CAMediaTimingFunction *timingFunction = | |
[[CAMediaTimingFunction alloc] initWithControlPoints:0.2f:0.0f:0.0f:1.0f]; | |
[CATransaction setAnimationTimingFunction:timingFunction]; | |
[UIView animateWithDuration:kCornerRadiusAnimationDuration animations:animationsBlock]; | |
[CATransaction commit]; | |
} |
This file contains 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
func updateOutline(isShowing: Bool, animated: Bool) { | |
let toColor: UIColor = isShowing ? .systemBlue : .clear | |
let toWidth: CGFloat = isShowing ? 2 : 0 | |
let animationDuration = 0.2 | |
if animated { | |
let borderColorAnimation: CABasicAnimation = CABasicAnimation(keyPath: "borderColor") | |
borderColorAnimation.fromValue = layer.borderColor | |
borderColorAnimation.toValue = toColor.cgColor | |
borderColorAnimation.duration = animationDuration | |
layer.add(borderColorAnimation, forKey: "borderColor") | |
layer.borderColor = toColor.cgColor | |
let borderWidthAnimation: CABasicAnimation = CABasicAnimation(keyPath: "borderWidth") | |
borderWidthAnimation.fromValue = layer.borderWidth | |
borderWidthAnimation.toValue = toWidth | |
borderWidthAnimation.duration = animationDuration | |
layer.add(borderWidthAnimation, forKey: "borderWidth") | |
layer.borderWidth = toWidth | |
} else { | |
layer.borderColor = toColor.cgColor | |
layer.borderWidth = toWidth | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment