1

In my app I have a ScrollView that holds a VStack. The VStack has an animation modifier. It also has one conditional view with a transition modifier. The transition works. However, when the view first appears, the content scales up with a starting width of 0. You can see this on the green border in the video below. This only happens if the VStack is inside the ScrollView or the VStack has the animation modifier.

I have tried different other things like setting a fixedSize or setting animation(nil) but I cannot get it to work.

I don't care if there is an animation at the beginning or if the view transitions onto the screen. But I definitely do not want the bad animation at the beginning. When I click on the button, the Text and the Button should both animate.

I also tested this behaviour with the following simplified code.

struct ContentView: View {
    @ObservedObject var viewModel = ViewModel()

    var body: some View {
        ScrollView {
            VStack(spacing: 32) {
                if self.viewModel.shouldShowText {
                    Text("Hello, World! This is a some text.")
                        .transition(
                            AnyTransition
                                .move(edge: .top)
                                .combined(
                                    with:
                                        .offset(
                                            .init(width: 0, height: -100)
                                        )
                                )
                        )
                }

                Button(
                    action: {
                        self.viewModel.didSelectButton()
                    },
                    label: {
                        Text("Button")
                            .font(.largeTitle)
                    }
                )
            }
            .border(Color.green)
            .animation(.easeInOut(duration: 5))
            .border(Color.red)

            HStack { Spacer() }
        }
        .border(Color.blue)
    }
}

class ViewModel: ObservableObject {
    @Published private var number: Int = 0

    var shouldShowText: Bool {
        return self.number % 2 == 0
    }

    func didSelectButton() {
        self.number += 1
    }
}

1 Answer 1

3

It works fine with Xcode 12 / iOS 14 (and stand-alone and in NavigationView), so I assume it is SwiftUI bug in previous versions.

Anyway, try to make animation be activated by value as shown below (tested & works)

  // ... other code
}
.border(Color.green)
.animation(.easeInOut(duration: 5), value: viewModel.number)   // << here !!
.border(Color.red)

and for this work it needs to make available published property for observation

class BlockViewModel: ObservableObject {
    @Published var number: Int = 0             // << here !!
 
    // ... other code
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you :) I have never seen the value: option before. Using it, there is no animation at the beginning and the transition still works as expected. It even works with the shouldShowText property so I didn't have to change my number property.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.