I need to create an animation for previous and next questions. The current question should move out and next/prev question should come in.
It functions nicely if you keep clicking Next.
But if I switch the direction to previous,
When I navigate from previous to next, the first click always results in a similar disparity.
Why is this so?
import SwiftUI
struct Question {
let id: Int
let text: String
}
extension AnyTransition {
static var slideRight: AnyTransition {
let insertion = AnyTransition.move(edge: .trailing)
let removal = AnyTransition.move(edge: .leading)
return .asymmetric(insertion: insertion, removal: removal)
}
static var slideLeft: AnyTransition {
let insertion = AnyTransition.move(edge: .leading)
let removal = AnyTransition.move(edge: .trailing)
return .asymmetric(insertion: insertion, removal: removal)
}
}
enum NavigationDirection {
case forward, backward
}
struct QuizView: View {
let questions = [
Question(id: 1, text: "Qustion 1: 1"),
Question(id: 2, text: "Qustion 2: to"),
Question(id: 3, text: "Qustion 3: III"),
Question(id: 4, text: "Qustion 4: 4444"),
Question(id: 5, text: "Qustion 5: 12345"),
Question(id: 6, text: "Qustion 6: FFFFFF")
]
@State private var currentQuestionIndex = 0
@State private var navigationDirection: NavigationDirection = .forward
var body: some View {
VStack(spacing: 20) {
Text(questions[currentQuestionIndex].text)
.id(questions[currentQuestionIndex].id) // Important for transition
.transition(navigationDirection == .forward ? .slideRight : .slideLeft)
.frame(maxWidth: .infinity, maxHeight: .infinity)
HStack {
Button("Previous") {
moveToPreviousQuestion()
}
.disabled(currentQuestionIndex == 0)
Spacer()
Button("Next") {
moveToNextQuestion()
}
.disabled(currentQuestionIndex == questions.count - 1)
}
}
.padding()
.animation(.easeInOut(duration: 1.0), value: currentQuestionIndex)
}
private func moveToNextQuestion() {
if currentQuestionIndex < questions.count - 1 {
navigationDirection = .forward
currentQuestionIndex += 1
}
}
private func moveToPreviousQuestion() {
if currentQuestionIndex > 0 {
navigationDirection = .backward
currentQuestionIndex -= 1
}
}
}
It performs nicely when there is a slight delay in the variable update:
private func moveToNextQuestion() {
navigationDirection = .forward
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
if currentQuestionIndex < questions.count - 1 {
currentQuestionIndex += 1
}
}
}
private func moveToPreviousQuestion() {
navigationDirection = .backward
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
if currentQuestionIndex > 0 {
currentQuestionIndex -= 1
}
}
}