빠른 UI를 사용하여 한 텍스트에서 다른 텍스트로 전환하는 애니메이션을 만드는 방법은 무엇입니까?

Dec 14 2020

문자열 배열이 있습니다. 예를 들면["Car", "Boat", "Van"]

어떻게하면에서 전환 그렇게하는 (이상의 문자열을 포함 할 수 있습니다) 배열의 텍스트의 변경 애니메이션 않습니다 CarBoatVan의 전환을 흐리게하여? 그리고 계속해서 이것을 반복하도록?

애니메이션 방법에 대한 아이디어가 이미 있지만 텍스트 전환에 갇혀있었습니다. 텍스트가 여기로 전환되지 않는 이유에 대한 질문을했습니다.-> 이 SwiftUI보기에서 텍스트가 아닌 크기가 애니메이션되는 이유는 무엇입니까?

그러나 실제로 텍스트를 전환하는 방법에 대해 별도의 질문을 작성하는 것이 더 나을 것이라고 생각했습니다.

답변

2 davidev Dec 14 2020 at 07:57

다음은 배열을 기반으로 텍스트를 애니메이션하는 가능한 솔루션입니다. 나는이 솔루션에서 Asperis 전이 아이디어를 사용하고 여기에

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

이미 @davidev 답변을 선택했습니다. 그러나 그의 대답을 바탕으로 이것이 내가 구현 한 것입니다. 건배 🍺

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
                }
            }
        }
    }
}