Text Typing & Retracting Animation
Typewriter effect that types out and deletes sentences with a blinking cursor.
SwiftUI Implementation
Pure Vanilla Swift • No DependenciestextTypingRetractingAnimation.swift
import SwiftUI
struct UseTextTypingRetractingAnimation: View {
var body: some View {
VStack {
TextTypingRetractingAnimation(textsToAnimate: ["We stay hungry.", "We stay foolish.", "We promise.", "Thank you Steve!"])
}
.padding()
}
}
#Preview {
UseTextTypingRetractingAnimation()
}
struct TextTypingRetractingAnimation: View {
var textsToAnimate: [String]
@State private var animatedText: String = ""
@State private var currentIndex: Int = 0
@State private var isAnimating: Bool = false
var body: some View {
VStack {
Text(animatedText)
.font(.system(size: 22, weight: .bold, design: .serif))
.padding()
.frame(height: 80)
}
.onAppear {
guard !textsToAnimate.isEmpty else { return }
animateText()
}
}
private func animateText() {
guard currentIndex < textsToAnimate.count else { return }
let text = textsToAnimate[currentIndex]
animatedText = ""
isAnimating = true
// Type out the text
for (index, character) in text.enumerated() {
DispatchQueue.main.asyncAfter(deadline: .now() + Double(index) * 0.12) {
animatedText.append(character)
// Check if it's the last character
if index == text.count - 1 {
// If it's not the last text, initiate the retraction animation
if currentIndex < textsToAnimate.count - 1 {
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
retractText()
}
} else {
// If it's the last text, stop the animation
isAnimating = false
}
}
}
}
}
private func retractText() {
let text = animatedText
for index in 0..<text.count {
DispatchQueue.main.asyncAfter(deadline: .now() + Double(index) * 0.1) {
guard !animatedText.isEmpty else { return }
animatedText.removeLast()
// Check if it's the last character
if animatedText.isEmpty {
// Move to the next text
currentIndex += 1
isAnimating = false
if currentIndex < textsToAnimate.count {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
animateText()
}
}
}
}
}
}
private func restartAnimation() {
currentIndex = 0
animatedText = ""
guard !textsToAnimate.isEmpty else { return }
animateText()
}
}Ready to copy and paste directly into any Xcode project running iOS 16.0+.
Recommended Use Cases
- First-run onboarding flows and feature introductions
- Paywalls, upgrade prompts, and subscription tiers
Component Details
- Category
- Texts & Typography
- iOS Compatibility
- iOS 16.0+
- Xcode Version
- Xcode 15+
- Platform
- iOS
- License Tier
- Free
- Themes & Contexts
- onboardingpaywall
- Keywords
- textanimationtypingretractingsteve jobs
C
Compot for iOS
Native SwiftUI playground app
Preview all 130+ components interactively on your device and copy code straight to Xcode with 1 tap.
Get Compot on the App StoreRelated SwiftUI Components
More components in Texts & Typography and related app architectures.
ButtonsiOS 16.0+
Primary Button Basic
High-emphasis prominent action button with standard SwiftUI prominence styling and haptic feedback.
View Component & Code
ButtonsiOS 16.0+
CTA Button Large Basic
Full-width, high-impact call-to-action button designed for onboarding screens, welcome flows, and paywalls.
View Component & Code
ButtonsiOS 16.0+
Secondary Button Basic
Medium-emphasis secondary action button styled for alternative user workflows and dismissal actions.
View Component & Code