1

I'm trying to animate the offset of a SwiftUI view, while at the same time fading out and removing a subview of that view. The problem I'm running into is that SwiftUI performs the offset and fade-out animations, but doesn't combine them.

What I want to achieve to animate the position of the whole SubView, while simultaneously fading out the subtitle text, so that the subtitle text moves vertically while fading in or out. I can achieve this by animating the opacity of the Text instead of removing it, but that means the text will still take up "layout space".

Is there a way to achieve this animation with the if showSubtitle statement?

The following code and GIF demonstrate the problem:

struct ContentView: View {
    @State private var showSubtitle = true
    var body: some View {
        SubView(showSubtitle: showSubtitle)
            .animation(.default)
            .offset(y: showSubtitle ? 100 : 0)
            .onTapGesture {
                self.showSubtitle.toggle()
            }
    }
}

struct SubView: View {
    let showSubtitle: Bool
    var body: some View {
        VStack {
            Text("Header")
            if showSubtitle {
                Text("Subtitle")
            }
        }
    }
}

Video

1
  • have you tried defining showSubtitle as a Binding instead of a constant? Commented Jul 3, 2020 at 15:35

1 Answer 1

2

Actually the observed behaviour is because .offset does not change layout, the view is stand at the same place. So when you remove subview it is removed in-place and animating that removal (with default .opacity transition). The part that starts offsetting does not contain already subview, so you don't see it in moving up part.

Here is something that might give some kind of effect you expect, but transitions are based on source size, so it is not so far and manually specified distance of offset. Anyway, try:

if showSubtitle {
    Text("Subtitle")
        .transition(AnyTransition.opacity.combined(with: AnyTransition.move(edge: .top)))
}

Tested with Xcode 12 / iOS 14

demo

Sign up to request clarification or add additional context in comments.

1 Comment

I don’t think it is because the offset not changing layout. I tried it with the position modifier, and the result is the same unfortunately. The transition workaround o kinda works, but it isn’t the most maintainable and flexible I think. Thanks for your answer though!

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.