I created an extension for UILabel to change the font size
extension UILabel { func animate(fontSize: CGFloat, duration: TimeInterval) { let startTransform = transform let oldFrame = frame var newFrame = oldFrame let scaleRatio = fontSize / font.pointSize newFrame.size.width *= scaleRatio newFrame.size.height *= scaleRatio newFrame.origin.x = oldFrame.origin.x - (newFrame.size.width - oldFrame.size.width) * 0.5 newFrame.origin.y = oldFrame.origin.y - (newFrame.size.height - oldFrame.size.height) * 0.5 frame = newFrame font = font.withSize(fontSize) transform = CGAffineTransform.init(scaleX: 1 / scaleRatio, y: 1 / scaleRatio); layoutIfNeeded() UIView.animate(withDuration: duration, animations: { self.transform = startTransform newFrame = self.frame }) { (Bool) in self.frame = newFrame } }
If you want to adjust the direction of the animation, use the method below and set a suitable reference point.
SWIFT
struct LabelAnimateAnchorPoint { // You can add more suitable archon point for your needs static let leadingCenterY = CGPoint.init(x: 0, y: 0.5) static let trailingCenterY = CGPoint.init(x: 1, y: 0.5) static let centerXCenterY = CGPoint.init(x: 0.5, y: 0.5) static let leadingTop = CGPoint.init(x: 0, y: 0) } extension UILabel { func animate(fontSize: CGFloat, duration: TimeInterval, animateAnchorPoint: CGPoint) { let startTransform = transform let oldFrame = frame var newFrame = oldFrame let archorPoint = layer.anchorPoint let scaleRatio = fontSize / font.pointSize layer.anchorPoint = animateAnchorPoint newFrame.size.width *= scaleRatio newFrame.size.height *= scaleRatio newFrame.origin.x = oldFrame.origin.x - (newFrame.size.width - oldFrame.size.width) * animateAnchorPoint.x newFrame.origin.y = oldFrame.origin.y - (newFrame.size.height - oldFrame.size.height) * animateAnchorPoint.y frame = newFrame font = font.withSize(fontSize) transform = CGAffineTransform.init(scaleX: 1 / scaleRatio, y: 1 / scaleRatio); layoutIfNeeded() UIView.animate(withDuration: duration, animations: { self.transform = startTransform newFrame = self.frame }) { (Bool) in self.layer.anchorPoint = archorPoint self.frame = newFrame } } }
OBJECTIVE-C
// You can add more suitable archon point for your needs #define kLeadingCenterYAnchorPoint CGPointMake(0.f, .5f) #define kTrailingCenterYAnchorPoint CGPointMake(1.f, .5f) #define kCenterXCenterYAnchorPoint CGPointMake(.5f, .5f) #define kLeadingTopAnchorPoint CGPointMake(0.f, 0.f) @implementation UILabel (FontSizeAnimating) - (void)animateWithFontSize:(CGFloat)fontSize duration:(NSTimeInterval)duration animateAnchorPoint:(CGPoint)animateAnchorPoint { CGAffineTransform startTransform = self.transform; CGRect oldFrame = self.frame; __block CGRect newFrame = oldFrame; CGPoint archorPoint = self.layer.anchorPoint; CGFloat scaleRatio = fontSize / self.font.pointSize; self.layer.anchorPoint = animateAnchorPoint; newFrame.size.width *= scaleRatio; newFrame.size.height *= scaleRatio; newFrame.origin.x = oldFrame.origin.x - (newFrame.size.width - oldFrame.size.width) * animateAnchorPoint.x; newFrame.origin.y = oldFrame.origin.y - (newFrame.size.height - oldFrame.size.height) * animateAnchorPoint.y; self.frame = newFrame; self.font = [self.font fontWithSize:fontSize]; self.transform = CGAffineTransformScale(self.transform, 1.f / scaleRatio, 1.f / scaleRatio); [self layoutIfNeeded]; [UIView animateWithDuration:duration animations:^{ self.transform = startTransform; newFrame = self.frame; } completion:^(BOOL finished) { self.layer.anchorPoint = archorPoint; self.frame = newFrame; }]; } @end
For example, to change the font size of a label to 30, the duration is 1 s from the center and the scale is longer. Just call
SWIFT
YOUR_LABEL.animate(fontSize: 30, duration: 1, animateAnchorPoint: LabelAnimateAnchorPoint.centerXCenterY)
OBJECTIVE-C
[YOUR_LABEL animateWithFontSize:30 duration:1 animateAnchorPoint:kCenterXCenterYAnchorPoint]
trungduc Nov 22 '17 at 14:07 2017-11-22 14:07
source share