es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La temporización de animación de SwiftUI .delay es incorrecta después de salir y volver a la vista.

Esta animación funciona correctamente cuando se visualiza por primera vez, pero el tiempo se desajusta al azar cuando se sale y vuelve a entrar en la aplicación (o si se navega fuera de la pantalla y se vuelve a ella). ¿Cómo se puede cambiar este código para mantener la sincronización de la animación después de salir de la pantalla y volver?

Este error se puede reproducir saliendo y volviendo a entrar en la aplicación varias veces.

Correct animation After several app exits and re-enters

import SwiftUI

struct ExampleView: View {
    @State var isAnimating: Bool = false

    let timing =  4.0
    let maxCounter: Int = 3

    var body: some View {
        ZStack {
            Circle()
                .stroke(
                    Color.blue.opacity(isAnimating ? 0.0 : 1.0),
                    style: StrokeStyle(lineWidth: isAnimating ? 0.0 : 15.0))
                .scaleEffect(isAnimating ? 1.0 : 0.0)
                .animation(
                    Animation.easeOut(duration: timing)
                    .repeatForever(autoreverses: false)
                    .delay(Double(0) * timing / Double(maxCounter) / Double(maxCounter)), value: isAnimating)

            Circle()
                .stroke(
                    Color.blue.opacity(isAnimating ? 0.0 : 1.0),
                    style: StrokeStyle(lineWidth: isAnimating ? 0.0 : 15.0))
                .scaleEffect(isAnimating ? 1.0 : 0.0)
                .animation(
                    Animation.easeOut(duration: timing)
                    .repeatForever(autoreverses: false)
                    .delay(Double(1) * timing / Double(maxCounter) / Double(maxCounter)), value: isAnimating)

            Circle()
                .stroke(
                    Color.blue.opacity(isAnimating ? 0.0 : 1.0),
                    style: StrokeStyle(lineWidth: isAnimating ? 0.0 : 15.0))
                .scaleEffect(isAnimating ? 1.0 : 0.0)
                .animation(
                    Animation.easeOut(duration: timing)
                    .repeatForever(autoreverses: false)
                    .delay(Double(2) * timing / Double(maxCounter) / Double(maxCounter)), value: isAnimating)
        }
        .frame(width: 200, height: 200, alignment: .center)
        .onAppear {
            isAnimating = true
        }
    }
}
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Una posible solución para mantener la sincronización del tiempo de la animación después de salir y regresar a la pantalla es eliminar el modificador onAppear y reemplazarlo por el modificador onReceive que escucha los cambios en el estado isAnimating.

    Esto asegura que la animación se inicie o reinicie cuando se muestra la vista o cuando cambia el estado isAnimating, independientemente de si la vista se mostró previamente o no.

    Aquí está el código modificado:

    import SwiftUI
    
    struct VistaEjemplo: Vista {
        @State var isAnimating: Bool = false
    
        let timing =  4.0
        let maxCounter: Int = 3
    
        var body: some View {
            ZStack {
                Circle()
                    .stroke(
                        Color.blue.opacity(isAnimating ? 0.0 : 1.0),
                        estilo: StrokeStyle(lineWidth: isAnimating ? 0.0 : 15.0))
                    .scaleEffect(isAnimating ? 1.0 : 0.0)
                    .animation(
                        Animation.easeOut(duration: timing)
                        .repeatForever(autoreverses: false)
                        .delay(Double(0) * timing / Double(maxCounter) / Double(maxCounter)), value: isAnimating)
    
                Circle()
                    .stroke(
                        Color.blue.opacity(isAnimating ? 0.0 : 1.0),
                        estilo: StrokeStyle(lineWidth: isAnimating ? 0.0 : 15.0))
                    .scaleEffect(isAnimating ? 1.0 : 0.0)
                    .animation(
                        Animation.easeOut(duration: timing)
                        .repeatForever(autoreverses: false)
                        .delay(Double(1) * timing / Double(maxCounter) / Double(maxCounter)), value: isAnimating)
    
                Circle()
                    .stroke(
                        Color.blue.opacity(isAnimating ? 0.0 : 1.0),
                        estilo: StrokeStyle(lineWidth: isAnimating ? 0.0 : 15.0))
                    .scaleEffect(isAnimating ? 1.0 : 0.0)
                    .animation(
                        Animation.easeOut(duration: timing)
                        .repeatForever(autoreverses: false)
                        .delay(Double(2) * timing / Double(maxCounter) / Double(maxCounter)), value: isAnimating)
            }
            .frame(width: 200, height: 200, alignment: .center)
            .onReceive([self.isAnimating].publicador.first()) { valor in
                withAnimation {
                    self.isAnimating = valor
                }
            }
        }
    }
    

    En este código modificado, el estado isAnimating solo se actualiza cuando cambia el valor del publicador isAnimating. Esto garantiza que la animación se inicie o reinicie cada vez que cambia el estado isAnimating, independientemente de si la vista se mostró previamente o no.

    Con este cambio, la animación debería ejecutarse de manera consistente incluso después de que se salga y entre en la aplicación o si se navega lejos de la pantalla y se vuelve a ella.

Comments are closed.