Skip to content

Instantly share code, notes, and snippets.

@Koshimizu-Takehito
Created February 15, 2025 02:45
Show Gist options
  • Save Koshimizu-Takehito/9aea2fda75a1b7c2f3260de5e633cf24 to your computer and use it in GitHub Desktop.
Save Koshimizu-Takehito/9aea2fda75a1b7c2f3260de5e633cf24 to your computer and use it in GitHub Desktop.
TypingText
import SwiftUI
struct ContentView: View {
private var title: String {
Item.sample.title
}
private var message: String {
Item.sample.message
}
@State private var progress: Double = 0
@State private var isOn = false
var body: some View {
VStack(alignment: .leading, spacing: 16) {
Text(title)
.font(.largeTitle)
.fontWeight(.bold)
TypingText(fullText: message, animatableData: progress)
.font(.custom("Courier", size: 20))
.lineSpacing(10)
}
.onChange(of: progress) { _, progress in
if progress.truncatingRemainder(dividingBy: 1) == 0 {
isOn = progress == 1
}
}
.onChange(of: isOn) { _, isOn in
withAnimation(.linear(duration: Double(message.count) / 30.0)) {
progress = isOn ? 1 : 0
}
}
.multilineTextAlignment(.leading)
.frame(maxHeight: .infinity)
.padding(.horizontal)
.ignoresSafeArea()
.overlay {
HStack {
Slider(value: $progress, in: 0...1)
Toggle(isOn: $isOn) {
Text("Toggle")
}
}
.frame(maxHeight: .infinity, alignment: .bottom)
.padding()
.toggleStyle(.button)
.fontWeight(.black)
}
.tint(.orange)
}
}
struct TypingText: View, Animatable {
var fullText: String
var animatableData: Double // 0...1
var body: some View {
Text(displayText)
}
private var displayText: AttributedString {
let text = fullText
let count = Int(Double(text.count) * min(max(animatableData, 0), 1))
let startIndex = text.index(text.startIndex, offsetBy: 0)
let endIndex = text.index(text.startIndex, offsetBy: count)
var visibles = AttributedString(text[startIndex..<endIndex])
visibles.foregroundColor = .red // .black
var invisibles = AttributedString(text[endIndex..<text.endIndex])
invisibles.foregroundColor = .black.opacity(0.2) // .clear
return visibles + invisibles
}
}
struct Item {
var title: String
var message: String
static let sample: Self = .init(
title: "SwiftUI\nFramework",
message: "SwiftUI is Apple’s declarative UI framework for cross-platform development. It simplifies UI building with state-driven rendering and real-time Xcode previews. Data binding and built-in components enhance efficiency and consistency."
)
}
#Preview {
ContentView()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment