迅速なUIを使用して、あるテキストから別のテキストへの切り替えをアニメーション化する方法は?

Dec 14 2020

文字列の配列があります。例えば["Car", "Boat", "Van"]

配列内のテキスト(より多くの文字列を含めることができる)の変更をアニメ化して、遷移をぼかすことによってからCarに切り替えるにはどうすればよいですか?そして、それが継続的にこれをループするように?BoatVan

アニメーション化の方法についてはすでに考えていますが、テキストの切り替えに行き詰まりました。ここでテキストが切り替わらない理由について質問しました->この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
                }
            }
        }
    }
}