I want to create an animation like showed in this video.
I already created a view that shows the current time, splitted in three boxes, but I dont know how to animate it. Thank you for your help!
This is my enviroment object, which gets the current time:
import SwiftUI
class TimeManager: ObservableObject {
@Published var date = Date()
@Published var oldDate = Date()
func timeString(timeFormat: String, date: Date) -> String {
let formatter = DateFormatter()
formatter.dateFormat = timeFormat
let time = formatter.string(from: date)
return time
}
// update time
var updateTimer: Timer {
withAnimation(.spring()){
Timer.scheduledTimer(withTimeInterval: 1, repeats: true,
block: {_ in
self.oldDate = self.date
self.date = Date()
})
}
}
}
And this is the view, which splits the time in boxes:
struct BoxesView: View {
@EnvironmentObject var timeManager: TimeManager
var body: some View {
HStack(spacing: 30) {
let timeElements = splitUpTime()
ForEach(timeElements, id: \.self) { timeElement in
SingleBoxElement(text: timeElement)
}
}.ignoresSafeArea()
}
func splitUpTime() -> Array<String> {
let splitDate = timeManager.timeString(timeFormat: "HH:mm:ss", date: timeManager.date).components(separatedBy: ":")
return splitDate
}
}
struct SingleBox: View {
let text: String
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 12)
.foregroundColor(.pink)
Text(text)
.foregroundColor(.white)
.font(.title)
.fontWeight(.semibold)
.monospacedDigit()
}.frame(width: 90, height: 90)
}
}
CodePudding user response:
Here's a quick example --
On each tap of the "Next" button, it increments the value... sliding the "old" string down-and-out the bottom and the "new" string down-and-in from the top:
import SwiftUI
struct TextTransition: View {
@State private var secondsValue = "21"
@State private var seconds: Int = 21
var body: some View {
VStack (spacing: 50) {
ZStack {
Text(secondsValue)
.font(.title)
.fontWeight(.semibold)
.monospacedDigit()
.foregroundColor(Color.white)
.frame(width: 60, height: 40)
.transition(AnyTransition.asymmetric(insertion: .move(edge: .top), removal: .move(edge: .bottom)))
.id("Seconds" secondsValue)
}
.background(Color.red)
.frame(width: 60, height: 40)
.clipped()
Button("Next") {
seconds = 1
withAnimation (.easeInOut(duration: 0.5)) {
self.secondsValue = "\(seconds)"
}
}
}
}
}
Now all you need to do is implement your TimeManager
to update secondsValue
(and minutes and hours values for their Text elements).