web-dev-qa-db-fra.com

Action répétée en continu à Swiftui

Comment puis-je faire un élément tel qu'une échelle de champ de texte, puis vers le bas continuellement?

J'ai ceci:

struct ContentView : View {
    @State var size:Double = 0.5

    var body: some View { 
        ZStack {
            Text("Hello!")
                 .padding()
                 .scaleEffect(size)
        }
    }
}

Je sais que j'ai besoin d'augmenter la taille, puis de la diminuer dans une sorte de boucle, mais ce qui suit ne peut être fait à Swifti:

while true {

  self.size += 0.8
  sleep(0.2)
  self.size -= 0.8

}
7
Isaac

L'utilisation d'une animation répétée sur une vue a un comportement étrange lorsqu'il est utilisé à l'intérieur si des déclarations.

Si vous voulez faire:

if something {
    BlinkingView()
}

utilisez une transition avec un modificateur d'animation, sinon la vue reste à l'écran même après something est défini sur False.

J'ai fait cette extension pour montrer une vue qui répète le changement d'un état à l'autre et à l'arrière:

extension AnyTransition {
    static func repeating<T: ViewModifier>(from: T, to: T, duration: Double = 1) -> AnyTransition {
       .asymmetric(
            insertion: AnyTransition
                .modifier(active: from, identity: to)
                .animation(Animation.easeInOut(duration: duration).repeatForever())
                .combined(with: .opacity), 
            removal: .opacity
        )
    }
}

Cela fait apparaître la vue et disparaître avec AnyTransition.opacity Et tant qu'il est montré qu'il passe entre le from et to état d'état avec un retard de duration.

Exemple d'utilisation:

struct Opacity: ViewModifier {
    private let opacity: Double
    init(_ opacity: Double) {
        self.opacity = opacity
    }

    func body(content: Content) -> some View {
        content.opacity(opacity)
    }
}

struct ContentView: View {
    @State var showBlinkingView: Bool = false

    var body: some View {
        VStack {
            if showBlinkingView {
                Text("I am blinking")
                    .transition(.repeating(from: Opacity(0.3), to: Opacity(0.7)))
            }
            Spacer()
            Button(action: {
                self.showBlinkingView.toggle()
            }, label: {
                Text("Toggle blinking view")
            })
        }.padding(.vertical, 50)
    }
}

Éditer:

Lorsque la condition de spectacle est vraie apparaissent, la transition ne démarre pas. Pour résoudre ce problème, je bascule la condition apparaissant de la vue de SuperView (le VStack dans mon exemple):

.onAppear {
    if self.showBlinkingView {
        self.showBlinkingView.toggle()
        DispatchQueue.main.async {
            self.showBlinkingView.toggle()
        }
    }
}
0