简体   繁体   中英

Animate Text Change of UILabel

I want to animate text changes in a UILabel.

For example: old text moves up and new text moves in from the bottom.

I already realised that I would need to labels. One for the old and one for the new text. The second UILabel is located below the first. Then both animate up.

However, how do you cut off the first label as it animates past the top portion of the frame?

Use a UIView 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 .

CALayer动画


(†) 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 .

Objective-C

The Swift UIView Extension can be solved in Objective-C with an Interface Extension .

1. The Interface Extension

@interface UIView (SO33632266)
- (void)pushTransition:(CFTimeInterval)duration;
@end

@implementation UIView (SO33632266)
// Usage: insert [view pushTransition:]; right before changing content
- (void)pushTransition:(CFTimeInterval)duration
{
    CATransition *animation = [CATransition new];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animation.type = kCATransitionPush;
    animation.subtype = kCATransitionFromTop;
    animation.duration = duration;
    [self.layer addAnimation:animation forKey:kCATransitionPush];
}
@end

2. pushTransition Invocation

[aLabel pushTransition:0.4];
aLabel.text = [[NSString alloc] initWithFormat:@"%ld", (long) ++self.count];

3. In Action

UILabel动画


One-off: without Interface Extension:

CATransition *animation = [CATransition animation];
animation.timingFunction = [CAMediaTimingFunction
    functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromTop;
animation.duration = 0.4;
[aLabel.layer addAnimation:animation forKey:@"kCATransitionPush"];

Invocation:

aLabel.text = [[NSString alloc] initWithFormat:@"%ld", (long) ++self.count];

QuartzCore provides a CATransition class for animated transition operations. CATransition has the following definition:

The CATransition class implements transition animations for a layer. You can specify the transition effect from a set of predefined transitions or by providing a custom CIFilter instance.


In order to have your label's text transition animated by pushing upwards the old text, you'll have to create an instance of CATransition and set its type to kCATransitionPush and its subtype to kCATransitionFromTop :

let animation = CATransition()
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
animation.type = kCATransitionPush
animation.subtype = kCATransitionFromTop
animation.duration = 1

You will then be able to animate your label's text transition by adding the animation to your label's layer:

label.layer.add(animation, forKey: nil)
label.text = "Some new content"

The following Swift 3 Playground code shows a possible implementation in order to animate a UILabel 's text transition using CATransition :

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {  
    let label: UILabel = {
        $0.frame.origin = CGPoint(x: 50, y: 50)
        $0.text = "Bob"
        $0.sizeToFit()
        return $0
    }(UILabel())
    let animation: CATransition = {
        $0.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        $0.type = kCATransitionPush
        $0.subtype = kCATransitionFromTop
        $0.duration = 1
        return $0
    }(CATransition())

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        view.addSubview(label)

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:)))
        view.addGestureRecognizer(tapGesture)
    }

    func toggle(_ sender: UITapGestureRecognizer) {
        label.layer.add(animation, forKey: nil)
        label.text = label.text == "Bob" ? "Dan" : "Bob"
        label.sizeToFit()
    }
}

let controller = ViewController()
PlaygroundPage.current.liveView = controller

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM