Animate text change in UILabel
Here is the code to make this work.
[UIView beginAnimations:@"animateText" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDuration:1.0f];
[self.lbl setAlpha:0];
[self.lbl setText:@"New Text";
[self.lbl setAlpha:1];
[UIView commitAnimations];
Animate Text Change of UILabel
Use aUIView
Extension
Animate in place using a single label:
- Leverage upon the built-in CALayer
animations, and a UIView
extension
- In the Storyboard, place the UILabel
inside a UIView
with Clip Subviews flag†.
- pushTransition
is applicable to most UIView
1. Extension
// Usage: insert view.pushTransition right before changing content
extension UIView {
func pushTransition(_ duration:CFTimeInterval) {
let animation:CATransition = CATransition()
animation.timingFunction = CAMediaTimingFunction(name:
kCAMediaTimingFunctionEaseInEaseOut)
animation.type = kCATransitionPush
animation.subtype = kCATransitionFromTop
animation.duration = duration
layer.add(animation, forKey: kCATransitionPush)
}
}
2. Invocation
if let aLabel = label {
aLabel.pushTransition(0.4) // Invoke before changing content
aLabel.text = "\(count)"
count += 1
}
3. Example
Animation with a kCAMediaTimingFunctionEaseInEaseOut
curve, a 0.4
second duration, and a kCATransitionFromTop
direction †.
(†) Clipping is an important step for desired effect.
Swift 2 and earlier, see Steve Baughman's comment:self.layer.addAnimation(animation, forKey: kCATransitionPush)
► Find this solution on GitHub and additional details on Swift Recipes.
UILabel text change animation flickers when one text is longer than other
Not sure exactly what is going on in your example as I could not produce this result. But animations are in many cases a pain and a lot of things may produce jumping views.
By having a bit more control over animation you might have better luck finding out the issue or fixing it. For your specific case it might already be enough to do your animation using snapshots. Check out the following:
@IBOutlet weak var label: UILabel!
private func animateAsCustom(applyChanges: @escaping (() -> Void)) {
guard let viewToMove = label else { return }
guard let panel = viewToMove.superview else { return }
guard let snapshotView = viewToMove.snapshotView(afterScreenUpdates: true) else { return }
applyChanges()
UIView.performWithoutAnimation {
panel.addSubview(snapshotView)
snapshotView.center = viewToMove.center
viewToMove.transform = CGAffineTransform(translationX: 0.0, y: 50.0) // TODO: compute values for translation
viewToMove.alpha = 0.0
}
UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseIn) {
viewToMove.transform = .identity
snapshotView.transform = CGAffineTransform(translationX: 0.0, y: -50.0)
snapshotView.alpha = 0.0
viewToMove.alpha = 1.0
} completion: { _ in
snapshotView.removeFromSuperview()
}
}
@IBAction func didTap() {
animateAsCustom {
self.label.numberOfLines = 1
self.label.text = "Can you see a flicker?"
self.label.textColor = .red
self.label.font = UIFont.systemFont(ofSize: 20)
}
}
@IBAction func didTapRev() {
animateAsCustom {
self.label.numberOfLines = 0
self.label.text = "Hello this\nis animation !!!"
self.label.textColor = .black
self.label.font = UIFont.systemFont(ofSize: 30)
}
}
This will still not fix the issue if you press one of the buttons before previous animation did finish. To fix that one as well some extra effort may be needed. But for now this solution could be enough.
Animate UILabel text between two numbers?
You can use the automatic transitions. It's working perfectly well :
// Add transition (must be called after myLabel has been displayed)
CATransition *animation = [CATransition animation];
animation.duration = 1.0;
animation.type = kCATransitionFade;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[myLabel.layer addAnimation:animation forKey:@"changeTextTransition"];
// Change the text
myLabel.text = newText;
This code works if myLabel is already displayed. If not myLabel.layer will be nil and the animation will not be added to the object.
in Swift 4 that would be:
let animation: CATransition = CATransition()
animation.duration = 1.0
animation.type = kCATransitionFade
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
myLabel.layer.add(animation, forKey: "changeTextTransition")
How to animate the textColor property of an UILabel?
This answer is obsolete, and is not a good solution for the original question. @strange 's answer below is much better and should be used instead of this answer: https://stackoverflow.com/a/20892927/76559
//Old answer below
The textColor
property is not specified as being animatable in the docs, so I don't think you can do it with a simple UIView animations block...
This could probably be done pretty crudely with an NSTimer
firing every couple of milliseconds, each time setting the colour gradually from one to the other.
I say this is crude because it would require an array or some other container of preset colour values going from the start colour to the finish colour, and I'm sure there's a way you could do this using core animation or something, I just don't know what it is.
How to animate UILabel text size (and color)
As I mentioned, applying a CGAffineTransform
to a UILabel
to scale it is frustrating for design-oriented developers, for two reasons.
- The
transform
doesn't account for tracking and font variants. San Francisco (Apple's system font) uses two distinct variants of its font depending on the text size.
iOS automatically applies the most appropriate variant based on the point size and the user's accessibility settings. Adjust tracking—the spacing between letters—appropriately.
SF Pro Text is applied to text 19 points or smaller, while SF Pro Display is applied to text 20 points or larger. Each variant has different "tracking" values — the spacing between letters — for each point size (see: the many tracking values under Font Usage and Tracking).
Unfortunately, CGAffineTransform
doesn't set a new pointSize
, which would otherwise force a redraw of the view. Applying a transform just scales the rasterized bitmap of the UILabel
, which means that fonts and tracking values aren't adaptive. So, if we're scaling our label by 2.0 from 10pt to 20pt, our resulting UILabel
at 20pt will still be using SF Pro Text with 12pt tracking, instead of SF Pro Display with 19pt tracking. You can see below that the red label is transformed and hence does not adjust its font.
- Transforming a view or layer leads to blurriness. As previously alluded to, Core Graphics doesn't re-render the view, but rather transforms the view's 2D map of pixels. The red label below is clearly blurry.
The Solution
Our best bet is to use CATextLayer
instead of UILabel
, which Apple says is:
A layer that provides simple text layout and rendering of plain or attributed strings.
The CATextLayer
docs list var string: Any?
, var font: CFTypeRef?
, var fontSize: CGFloat
, var foregroundColor: CGColor?
and more as properties, which most of the time is all we need. Perfect!
All we need to do is add a CAPropertyAnimation
— like CABasicAnimation
— to the CATextLayer
to animate its properties, like so:
// Create the CATextLayer
let textLayer = CATextLayer()
textLayer.string = "yourText"
textLayer.font = UIFont.systemFont(ofSize: startFontSize)
textLayer.fontSize = startFontSize
textLayer.foregroundColor = UIColor.black.cgColor
textLayer.contentsScale = UIScreen.main.scale
textLayer.frame = view.bounds
view.layer.addSublayer(textLayer)
// Animation
let duration: TimeInterval = 10
textLayer.fontSize = endFontSize
let fontSizeAnimation = CABasicAnimation(keyPath: "fontSize")
fontSizeAnimation.fromValue = startFontSize
fontSizeAnimation.toValue = endFontSize
fontSizeAnimation.duration = duration
textLayer.add(fontSizeAnimation, forKey: nil)
and voila! The black text below is our properly scaled CATextLayer
. Sharp and with the correct font variant.
h/t to Yinan for the code: https://stackoverflow.com/a/42047777/4848310. Yinan also discusses how to use CATextLayer
with Auto Layout constraint-based animations.
Bonus! This also works for animating text color! Just use the foregroundColor
property.
Is there a way to animate changing a UILabel's textAlignment?
Set the UILabel frame size to exactly contain the text and center the UILabel in your view.
self.monthLabel.text = @"February";
[self.monthLabel sizeToFit];
self.monthLabel.center = parentView.center; // You may need to adjust the y position
Then set the alignment which should not affect the layout since there will be no extra space.
self.monthLabel.textAlignment = NSTextAlignmentLeft;
Next, animate the UILabel frame size so it slides over where you want it.
[UIView animateWithDuration:0.5
animations:^{
CGRect frame = self.monthLabel.frame;
frame.origin.x = 10;
self.monthLabel.frame = frame;
} completion:nil];
How would one animate UILabel text property with CoreAnimation in Swift?
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
var counter = 0
override func viewDidLoad() {
super.viewDidLoad()
let timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("animate"), userInfo: nil, repeats: true)
timer.fire()
}
func animate() {
UIView.transitionWithView(label,
duration: 1.0,
options: [.CurveEaseInOut],
animations: { () -> Void in
self.counter += 1
self.label.text = "\(self.counter)"
}, completion: nil)
}
}
How to animate text color of a UILabel like a progress bar
To achieve it, follow below steps:
- Create 2
UILabel
(trackLabel
andprogressLabel
). trackLabel
haveblackColor
andprogressLabel
haveredColor
.- Make
progressLabel
overlaptrackLabel
, same leading, top and bottom. - Give
trackLabel
full width with text andprogressLabel
0 width. - Set
progressLabel.lineBreakMode = NSLineBreakByClipping;
- When you need to animate progress, increase width of
progressLabel
.
For more detail, you can check my demo project.
Related Topics
Calayer with Transparent Hole in It
How to Get the Font Name from an Otf or Ttf File
Writing Handler for Uialertaction
How to Rotate Orientation Programmatically in Swift
Uibutton Fails to Properly Register Touch in Bottom Region of iPhone Screen
Exc_Bad_Access When Building Nspredicate
How to Set iOS Status Bar Background Color in React Native
Xcode 10 (iOS 12) Does Not Contain Libstdc++6.0.9
Class Is Implemented in Both, One of the Two Will Be Used. Which One Is Undefined
How to Style Uitextview to Like Rounded Rect Text Field
How to Keep Uitableview Contentoffset After Calling -Reloaddata
Uitableview with Static Cells Does Not Appear
Open Phone Settings Programmatically in iOS9
How to Detect Swipe Gesture in iOS
[Nsobject:Anyobject]' Does Not Have a Member Named 'Subscript' Error in Xcode 6 Beta 6