UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Animating Form

Forums > SwiftUI

Hi. I try to create a Form with multiple fields. At the top is a Toggle, which shows or hides the other fields. My problem is, i dont manage to animate the transition. It animates somehow. But it doesnt look right.

import SwiftUI

struct TestForm: View {

    @State var sectionActive = false

    var body: some View {
        Form {
            Section (header: Text("Section 1")) {
                Toggle("Activate Section", isOn: $sectionActive.animation())
                if sectionActive {
                    Text("Item 1")
                    Text("Item 2")
                    Text("Item 3")
                }
            }
        }
    }
}

struct TestForm_Previews: PreviewProvider {
    static var previews: some View {
        TestForm()
    }
}

1      

UPDATE 1: I wrote the response below; then continued testing. Seems no matter what value I enter for duration, the change happens immediately. Now I am confused. Apologize for posting an answer that doesn't work. Ooooof.

UPDATE 2: Seems that adding the animation to the Form works. Change the duration to 5 seconds and run in a simulator with the debug flag Slow Animations. I agree with you, this still doesn't look right.

Original Post


Nice! +1 for not naming your view "ContentView".

I try to think of animations as a "before" and "after" snapshots of a view. Think of your kitchen "before" cooking a big meal, and the state of your kitchen "after" cooking a big meal. The before and after states are marked by the variable, isMealDone.

When isMealDone changes from false to true we take a snapshot of the kitchen's final state. SwiftUI then produces all the frames inbetween.

You want to animate the kitchen, but in your code it looks like you're animating the toggle (the light switch).

Also, the animation() method has been deprecated. It works now, but in future releases it won't. The new method is .animation( animation, value:).

In short this modifier will animate the view you attach it to, using the animation you specify (.default, .easeIn, etc). Plus it will execute this animation when the specified value changes. SwiftUI will look at the state before the value changes and after the value changes, and SwiftUI will generate all the inbetween frames for you.

struct TestForm: View {
    @State var sectionActive = false
    var body: some View {
        Form {
            Section (header: Text("Section 1")) {
                Toggle("Activate Section", isOn: $sectionActive)
                if sectionActive {
                    List {
                        Text("Item 1")
                        Text("Item 2")
                        Text("Item 3")
                    }
                }
            }
        }
        // Add the animation to the Form
        .animation(.easeOut(duration: 2.0), value: sectionActive)  // Test in simulator with Slow Animations on.
    }
}

2      

If you put the items in their own section, the animation looks alot smoother. It also looks better if you only have two text items. I have no idea why, I was just playing around with it and none of that may help. Even with it being in its own section, the duration, or any other modifiers to the animation don't seem to do anything, unlike the text when the Button is pressed.

struct TestForm: View {
    @State private var sectionActive = false
    @State private var text = ""
    var body: some View {
        Form {
            Section (header: Text("Section 1")) {
                Toggle("Activate Section", isOn: $sectionActive.animation())
            }
            if sectionActive {
                Section {
                    Text("Item 1")
                    Text("Item 2")
                    Text("Item 3")
                    Text(text)
                }
                Button("Tap Me") {
                    withAnimation(.easeInOut(duration: 2).repeatCount(3)) {
                    text = "I've been tapped"
                    }
                }
            }
        }
    }
}

2      

Thank you for your answers. The question wasn't that important to me. I was just curious why it doesn't work well for me. @Obelix, attaching the animation() directly to the toggle, I believe, was also shown by Paul as a possibility. I'm thinking that the transition modifier for the form is buggy. It works great with two items , but get confusied with more items.

1      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.