SwiftUI:如何为ViewThatFits内部的视图切换添加动画?
为ViewThatFits内部视图切换添加动画效果的实现方案
问题描述
希望为ViewThatFits内部的视图切换添加过渡、匹配几何效果等动画。当前拖动滑块调整ViewThatFits高度时,视图会在临界值处无动画切换,示例代码如下:
import SwiftUI struct ContentView: View { @State private var height: CGFloat = 100.0 var body: some View { VStack { Spacer() Slider(value: $height, in: 10.0...100.0, step: 1.0) Spacer() ViewThatFits { Rectangle() .fill(.red) .frame(height: 70.0) Rectangle() .fill(.blue) .frame(height: 30.0) } .frame(height: height) Spacer() } } } #Preview { ContentView() }
可行实现方案
方案一:手动跟踪适配状态 + 过渡动画
ViewThatFits的自动切换逻辑无法直接附加动画,因此可以手动判断容器高度与视图高度的关系,通过状态变量控制视图显示,并添加过渡动画:
import SwiftUI struct ContentView: View { @State private var height: CGFloat = 100.0 @State private var showRedView = true // 跟踪当前显示的视图 var body: some View { VStack { Spacer() Slider(value: $height, in: 10.0...100.0, step: 1.0) .onChange(of: height) { newValue in // 根据容器高度判断显示视图,用withAnimation触发动画 withAnimation(.easeInOut(duration: 0.3)) { showRedView = newValue >= 70 } } Spacer() // 手动切换视图并添加过渡效果 if showRedView { Rectangle() .fill(.red) .frame(height: 70.0) .transition(.scale.combined(with: .opacity)) } else { Rectangle() .fill(.blue) .frame(height: 30.0) .transition(.scale.combined(with: .opacity)) } .frame(height: height) Spacer() } } } #Preview { ContentView() }
方案二:使用matchedGeometryEffect实现几何匹配动画
如果需要两个视图切换时的大小、位置平滑过渡,可以结合matchedGeometryEffect实现连贯的视觉效果:
import SwiftUI struct ContentView: View { @State private var height: CGFloat = 100.0 @State private var showRedView = true private let shapeID = UUID() // 共享的几何匹配标识 var body: some View { VStack { Spacer() Slider(value: $height, in: 10.0...100.0, step: 1.0) .onChange(of: height) { newValue in withAnimation(.easeInOut(duration: 0.3)) { showRedView = newValue >= 70 } } Spacer() ZStack { // 始终渲染两个视图,仅显示目标视图,配合几何匹配实现平滑过渡 if showRedView { Rectangle() .fill(.red) .frame(height: 70.0) .matchedGeometryEffect(id: shapeID, in: .global) } else { Rectangle() .fill(.blue) .frame(height: 30.0) .matchedGeometryEffect(id: shapeID, in: .global) } } .frame(height: height) Spacer() } } } #Preview { ContentView() }
说明
- 方案一逻辑简单直观,通过
transition可快速实现淡入淡出、缩放等基础过渡效果。 - 方案二利用几何匹配让两个视图共享布局信息,切换时会有自然的大小/位置过渡,适合追求连贯视觉体验的场景。
内容的提问来源于stack exchange,提问作者Malburrito
相关产品推荐
相关产品推荐

