WWDC‐style per‐line text reveal & hide animation for UILabel 🚀
IMG_0675.MP4
- 🔠 Line‐by‐line staggered animation (cascade)
↕️ Opacity 0 → 1 and Y‐offset 8pt → 0- 📐 Scale 0.96 → 1.0 (anchor at bottom)
- 🌫️ Blur 8 → 0 (iOS 17+ GPU via
CIFilter; fallback on iOS 16 toUIVisualEffectView) ▶️ Animate In (animateIn) and ⏹️ Animate Out (animateOut)- 🪄 Triggers only when the label’s superview exists
- ⚡️ Caching of TextKit line layout for performance
- iOS 16.4+
- Swift 5.7+
- UIKit
i️ Important: The original
UILabelbeing animated must have:
lineBreakMode = .byWordWrapping- Initially
isHidden = true
-
Copy
LineByLineTextAnimator.swiftinto your project. -
Ensure you import:
import UIKit import CoreText import CoreImage
// Ensure label.frame is final and label.layoutIfNeeded() has been called label.isHidden = true // initial state LineByLineTextAnimator.animateIn( label: label, // your multiline UILabel totalDuration: 0.56, // optional, default 0.56s cascadeFraction: 0.45 // optional, default 0.45 )
// Hide immediately and play reverse animation label.isHidden = true LineByLineTextAnimator.animateOut( label: label, totalDuration: 0.56, cascadeFraction: 0.45 )
In your view controller:
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // Reveal once label.isHidden = true LineByLineTextAnimator.animateIn(label: label) } @IBAction func didTapHide(_ sender: UIButton) { // Hide on demand label.isHidden = true LineByLineTextAnimator.animateOut(label: label) }
- Timing: adjust
totalDuration&cascadeFraction. - Spring physics: tweak
UISpringTimingParameters(mass:stiffness:damping:initialVelocity:)in the code. - Blur radius: modify values in the
CIFilteror fallback animation.
- Call
label.layoutIfNeeded()before animation. - Reuse UILabels to benefit from line‐layout caching.
MIT — free to use and modify.