Rengers
Rengers

Reputation: 15218

Animate removing/adding SwiftUI view while animating offset

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

Upvotes: 1

Views: 2186

Answers (1)

Asperi
Asperi

Reputation: 257583

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

Upvotes: 2

Related Questions