Заставляем текст пульсировать в SwiftUI

#swift #animation #swiftui

#swift #Анимация #swiftui

Вопрос:

Итак, я пытаюсь заставить некоторый текст исчезать, чтобы придать эффект пульсирующего типа, это код, который у меня есть сейчас:

 struct SignInView: View {
    @State private var opacity: Double = 0.0
    @State private var pulseDown: Bool = false
    
    var body: some View {
        VStack(alignment: .center) {
            Spacer()
            
            Button(action: {
                AppDelegate.signInWithGoogle()
            }, label: {
                Text("Sign In")
                    .foregroundColor(Color.green)
                    .opacity(opacity)
            })
            
            Spacer()
        }
        .padding()
        .onAppear {
            self.pulsateText()
        }
    }
    
    private func pulsateText() {
        DispatchQueue.init(label: "Pulse").asyncAfter(deadline: .now()   0.01) {
            if self.pulseDown {
                self.opacity -= 0.02
            } else {
                self.opacity  = 0.02
            }
            
            if self.opacity > 1 {
                self.pulseDown = true
            } else if self.opacity < 0.1 {
                self.pulseDown = false
            }
            
            self.pulsateText()
        }
    }
}
  

Это делает именно то, что я хочу, и выглядит хорошо, но я не могу избавиться от ощущения, что бесконечный рекурсивный цикл — неправильный способ сделать это. Я полагаю, я мог бы сделать бесконечное время вместо бесконечной рекурсии, хотя это все еще кажется не идеальным. Есть ли лучший способ добиться этого?

Ответ №1:

Есть более простой способ, более похожий на SwiftUI. Это работает с использованием метода Animation ‘s repeatForever(autoreverses:) :

 struct SignInView: View {

    @State private var visible = true
    
    var body: some View {
        VStack {
            Spacer()
            
            Button(action: {
                print("Sign in with Google")
//                AppDelegate.signInWithGoogle()
            }, label: {
                Text("Sign In")
                    .foregroundColor(Color.green)
                    .opacity(visible ? 1 : 0)
            })
            
            Spacer()
        }
        .padding()
        .onAppear(perform: pulsateText)
    }
    
    private func pulsateText() {
        withAnimation(Animation.easeInOut.repeatForever(autoreverses: true)) {
            visible.toggle()
        }
    }
}
  

Комментарии:

1. Это то, что я искал, спасибо! Есть ли простой способ замедлить его? Редактировать: Разобрался, просто нужно передать параметр длительности в easeInOut еще раз спасибо!

2. Кажется, что после последнего обновления Xcode он больше не работает — теперь весь вид перемещается из верхнего левого угла в середину экрана и обратно в цикле, есть идеи о том, как это исправить?

3. @Quinn У меня это все еще работает, поэтому вы, должно быть, что-то изменили с тех пор (например, добавили анимацию к любым другим представлениям в VStack).

4. нет, только что обновленный Xcode — он все еще работает, если я создаю его на своем старом компьютере с точно таким же кодом — запуск его на моем новом компьютере с более новой версией Xcode дает мне сумасшедшие результаты