I’m trying to figure out how to change the height of a SwiftUI view with animation, without affecting the position of its subviews. I have an HStack containing some text objects. I want to animate the height of the view from 0 to 40 like so:
Note that the text objects shouldn't move as the parent view height changes (they should be anchored to the top of the parent view). I’ve tried the standard transitions such as: .transition(.scale(scale: 0, anchor: UnitPoint.top)). But that scales the entire view, including the subviews.
Here’s the view code:
struct SampleView: View {
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 20) {
let strings = ["Text 1", "Text 2", "Text 3"]
ForEach(strings, id: \.self) { string in
Text(string)
}
}
.foregroundStyle(Color.white)
}
.background(Color.orange)
}
}
An instance of this SampleView is created when a button action withAnimation block updates a variable.
Any suggestions?
You can create a custom transition that scales a mask
of the view.
struct RevealTransition: Transition {
func body(content: Content, phase: TransitionPhase) -> some View {
content.mask {
Rectangle()
.scaleEffect(y: phase.isIdentity ? 1 : 0, anchor: .top)
}
}
}
extension AnyTransition {
static var reveal: AnyTransition { AnyTransition(RevealTransition()) }
}
Example usage:
@State private var show = false
var body: some View {
VStack {
if show {
SampleView()
.transition(.reveal)
}
Button("Animate") {
show.toggle()
}
}
.animation(.default, value: show)
}
If you want the view to disappear in a different way, edit the body
as needed, or use an asymmetric
transition.