Skip to content

Instantly share code, notes, and snippets.

@SergLam
Last active May 31, 2022 17:51
Show Gist options
  • Save SergLam/491e156099c67004c517a1add784c776 to your computer and use it in GitHub Desktop.
Save SergLam/491e156099c67004c517a1add784c776 to your computer and use it in GitHub Desktop.
UIView animation with CABasicAnimation - border width and color
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];
}
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