簡體   English   中英

SwiftUI - 按下按鈕時動畫視圖

[英]SwiftUI - Animate a view on button press

我剛剛完成了#hackingwithswift 的第 6 課。 我正在為一個根本不應該那么難的挑戰而生氣......

在這里,我有一個名為 GuessTheFlag 的工作游戲,其中用戶必須選擇指示的正確標志,然后在傳遞到下一輪之前收到警報。

我的問題很簡單:我想讓不正確的標志視圖變得不透明,並且在選擇答案時讓正確的標志視圖旋轉 360 度。 這應該全部發生在警報之后,直到用戶單擊“繼續”。

可選:我還想完全刪除警報,並在旋轉動畫完成后讓游戲進入下一輪。 我可以將圓形更改綁定到動畫的結尾嗎? 還是我必須使用某種 sleep() 命令?

import SwiftUI

struct FlagView: View {
    var flag: String
    
    var body: some View {
        Image(flag)
            .renderingMode(.original)
            .clipShape(Capsule())
            .overlay(Capsule().stroke(Color.black, lineWidth: 2))
            .shadow(color: .black, radius: 2)
    }
    
}

struct ContentView: View {
    @State private var countries = ["Estonia", "France", "Germany", "Ireland", "Italy", "Nigeria", "Poland", "Russia", "Spain", "UK", "US"].shuffled()
    
    @State private var correctAnswer = Int.random(in: 0...2)
    @State private var showingScore = false
    @State private var scoreTitle = ""
    @State private var score = 0
    @State private var animate = false
    
    var alert: Alert {
        if scoreTitle == "Wrong" {
            return Alert(title: Text(scoreTitle), message: Text("The correct answer was \(countries[correctAnswer])"), dismissButton: .default(Text("Restart")) {
                self.askQuestion()
                animate = false
            })
        }
        else {
            return Alert(title: Text(scoreTitle), message: Text("Your Score is \(score)"), dismissButton: .default(Text("Continue")) {
                self.askQuestion()
                animate = false
            })
        }
        
    }

    var body: some View {
        ZStack{
            LinearGradient(gradient: Gradient(colors: [.black,.blue, .orange]), startPoint: .top, endPoint: .bottom).edgesIgnoringSafeArea(.all)
            
            VStack(spacing: 40) {
                VStack{
                    Text("Tap the flag of")
                        .foregroundColor(.white)
                    Text(countries[correctAnswer])
                        .font(.largeTitle)
                        .fontWeight(.black)
                        .foregroundColor(.white)
                }
                
                ForEach(0 ..< 3){ number in
                    Button(action: {
                        withAnimation {
                            self.flagTapped(number)
                            animate.toggle()
                        }
                    }) {
                        FlagView(flag: self.countries[number])
                    }
                }
                
                Text("Your Score is \(score)")
                    .font(.headline)
                    .fontWeight(.black)
                    .foregroundColor(Color.white)
                
                Spacer()
            }
        }
        .alert(isPresented: $showingScore) {
            alert
        }
    }

    func flagTapped(_ number: Int) {
        if number == correctAnswer {
            scoreTitle = "Correct"
            score += 1
            
        } else {
            scoreTitle = "Wrong"
            score = 0
            
        }
        
        showingScore = true
        
    }
    
    func askQuestion() {
        countries.shuffle()
        correctAnswer = Int.random(in: 0...2)
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

任何幫助,將不勝感激! 提前致謝

只需在FlagView上應用視圖修飾符opacityrotationEffect而不是使用離散值(例如.opacity(0.1) )使其成為有條件的:

.opacity((self.animate && number != correctAnswer) ? 0.1 : 1.0)

動畫部分將通過 SwiftUI 自動完成。 請參閱下面的我的工作示例:

import SwiftUI

struct FlagView: View {
    var flag: String
    
    var body: some View {
        Text(flag)
    }
    
}

struct ContentView: View {
    @State private var countries = ["Estonia", "France", "Germany", "Ireland", "Italy", "Nigeria", "Poland", "Russia", "Spain", "UK", "US"].shuffled()
    
    @State private var correctAnswer = Int.random(in: 0...2)
    @State private var showingScore = false
    @State private var scoreTitle = ""
    @State private var score = 0
    @State private var animate = false
    
    var alert: Alert {
        if scoreTitle == "Wrong" {
            return Alert(title: Text(scoreTitle), message: Text("The correct answer was \(countries[correctAnswer])"), dismissButton: .default(Text("Restart")) {
                self.askQuestion()
            })
        }
        else {
            return Alert(title: Text(scoreTitle), message: Text("Your Score is \(score)"), dismissButton: .default(Text("Continue")) {
                self.askQuestion()
            })
        }
        
    }

    var body: some View {
        ZStack{
            LinearGradient(gradient: Gradient(colors: [.black,.blue, .orange]), startPoint: .top, endPoint: .bottom).edgesIgnoringSafeArea(.all)
            
            VStack(spacing: 40) {
                VStack{
                    Text("Tap the flag of")
                        .foregroundColor(.white)
                    Text(countries[correctAnswer])
                        .font(.largeTitle)
                        .fontWeight(.black)
                        .foregroundColor(.white)
                }
                
                ForEach(0 ..< 3){ number in
                    Button(action: {
                        withAnimation(.easeInOut(duration: 0.5)) {
                            self.animate = true
                        }
                        self.flagTapped(number)
                    }) {
                        FlagView(flag: self.countries[number])
                            .opacity((self.animate && number != correctAnswer) ? 0.1 : 1.0)
                            .rotationEffect(.init(degrees: (self.animate && number == correctAnswer) ? 360.0 : 0.0))
                    }
                }
                
                Text("Your Score is \(score)")
                    .font(.headline)
                    .fontWeight(.black)
                    .foregroundColor(Color.white)
                
                Spacer()
            }
        }
        .alert(isPresented: $showingScore) {
            alert
        }
    }

    func flagTapped(_ number: Int) {
        if number == correctAnswer {
            scoreTitle = "Correct"
            score += 1
            
        } else {
            scoreTitle = "Wrong"
            score = 0
            
        }
        
        showingScore = true
        
    }
    
    func askQuestion() {
        self.animate = false
        countries.shuffle()
        correctAnswer = Int.random(in: 0...2)
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

為了您的選購問題(如例如,你可以引入一個自定義的修改在這里)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM