Reputation: 15218
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")
}
}
}
}
Upvotes: 1
Views: 2186
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
Upvotes: 2