Jak animować przełączanie się z jednego tekstu na inny za pomocą szybkiego interfejsu użytkownika?

Dec 14 2020

Mam tablicę ciągów. Na przykład["Car", "Boat", "Van"]

Jak mam anime zmienić tekst w tablicy (która może zawierać więcej ciągów), aby zmieniał się z Carna Boatna Vanprzez rozmycie przejścia? I żeby ciągle to zapętlał?

Mam już pomysł na animację, ale utknąłem przy przełączaniu tekstu. Zadałem pytanie, dlaczego tekst się tutaj nie przełącza -> Dlaczego rozmiar jest animowany, a nie tekst w tym widoku SwiftUI?

Pomyślałem jednak, że lepiej byłoby napisać osobne pytanie, jak właściwie zmienić tekst.

Odpowiedzi

2 davidev Dec 14 2020 at 07:57

Oto możliwe rozwiązanie animacji tekstu na podstawie tablicy. Użyłem Asperis pomysł przejścia z tego rozwiązania tutaj

struct ContentView: View {
    var array = ["First", "Second", "Third"]
    @State var shortString = true
    
    @State var currentIndex : Int = 0
    @State var firstString : String = ""
    @State var secondString : String = ""

    var body: some View {

        VStack {
            if shortString {
               Text(firstString).font(.title).fixedSize()
               .transition(AnyTransition.opacity.animation(.easeInOut(duration:1.0)))
            }
            if !shortString {
                Text(secondString).font(.title).fixedSize()
                    .transition(AnyTransition.opacity.animation(.easeInOut(duration:1.0)))
            }
        }
        .animation(.default)
        .onAppear {
            firstString = array[0]
            secondString = array[1]
            
            let timer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { _ in
                if (shortString) {
                    if currentIndex == array.count - 1 {
                        self.secondString = array[0]
                        currentIndex = 0
                    }
                    else {
                        self.secondString = array[currentIndex+1]
                        currentIndex += 1
                    }
                }
                else {
                    if currentIndex == array.count - 1 {
                        self.firstString = array[0]
                        currentIndex = 0
                    }
                    else {
                        self.firstString = array[currentIndex+1]
                        currentIndex += 1
                    }
                }
                shortString.toggle()
            }
        }
    }
}
Justacoder Dec 14 2020 at 09:02

Wybrałem już odpowiedź @davidev. Ale na podstawie jego odpowiedzi wdrożyłem to. Pozdrawiam 🍺

struct ContentView: View {
    var array = ["First", "Second", "Third"]
    @State var currentIndex : Int = 0
    @State var firstString : String = ""
    @State var timer: Timer? = nil
    @State var isBlurred = false
    
    var body: some View {
        VStack {
            Text(firstString).blur(radius: isBlurred ? 6 : 0)
        }.onAppear {
            self.timer = newTimer
        }
    }
    
    var newTimer: Timer {
        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { v in
            let rndTime = [0.5, 0.3, 0.7, 1.0].randomElement()! // I wanted a random time up to 1 second.
            v.invalidate()
            currentIndex += 1
            if currentIndex == array.count { currentIndex = 0 }
            DispatchQueue.main.asyncAfter(deadline: .now() + rndTime) {
                self.isBlurred.toggle()
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                    self.isBlurred.toggle()
                    firstString = array[currentIndex]
                    self.timer = newTimer
                }
            }
        }
    }
}