Last active
July 23, 2024 15:58
-
-
Save kaunteya/828aa10dd970c8b1396e2a3b37b56a6e to your computer and use it in GitHub Desktop.
SwiftUI view that displays content gradually
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// AnimatedText.swift | |
// | |
// Created by Kauntey Suryawanshi on 23/07/24. | |
// | |
import SwiftUI | |
struct AnimatedText: View { | |
enum Speed { | |
case fast, normal, slow | |
var duration: Duration { | |
switch self { | |
case .fast: .milliseconds(50) | |
case .normal: .milliseconds(100) | |
case .slow: .milliseconds(200) | |
} | |
} | |
/// Newline takes a longer wait | |
var durationNewLine: Duration { | |
switch self { | |
case .fast: .milliseconds(500) | |
case .normal: .milliseconds(1000) | |
case .slow: .milliseconds(2000) | |
} | |
} | |
} | |
let text: AttributedString | |
let speed: Speed | |
let wait: Duration | |
@State private var endIndex: AttributedString.Index | |
init(_ text: AttributedString, speed: Speed = .normal, wait: Duration = .zero) { | |
self.text = text | |
self.wait = wait | |
self.speed = speed | |
endIndex = self.text.startIndex | |
} | |
init(_ text: String, speed: Speed = .normal, wait: Duration = .zero) { | |
self.init(AttributedString(text), speed: speed, wait: wait) | |
} | |
var body: some View { | |
Group { | |
Text(AttributedString(text[text.startIndex ..< endIndex])) | |
+ Text(AttributedString(text[endIndex ..< text.endIndex])) | |
.foregroundColor(.clear) | |
} | |
.animation(.default, value: endIndex) | |
.task { | |
try? await Task.sleep(for: wait) | |
for i in text.characters.indices { | |
if text.characters[i].isNewline { | |
endIndex = i | |
try? await Task.sleep(for: speed.durationNewLine) | |
} else if text.characters[i].isWhitespace || text.characters.endIndex == i { | |
endIndex = i | |
try? await Task.sleep(for: speed.duration) | |
} | |
} | |
endIndex = text.endIndex | |
} | |
} | |
} | |
#Preview { | |
var attrString = AttributedString("Mark my words\n") | |
attrString.font = Font(NSFont.systemFont(ofSize: 21)) | |
attrString.append(AttributedString("Long term capital gains for all asset classes is going to be 12.5%. You may worry about your stocks and equity funds. Actually that is very less of your concern.\nYou pay 2.5% more than earlier now.")) | |
return VStack(alignment: .leading, spacing: 10) { | |
AnimatedText(attrString, speed: .normal) | |
} | |
.padding() | |
.frame(width: 500, height: 500) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Demo
Untitled.mov
This SwiftUI view displays text gradually.