SwiftUI:窗口调整大小时为LazyVGrid布局变化添加动画
macOS下LazyVGrid布局调整的动画实现方案
问题描述
我在macOS应用里用了LazyVGrid组件,调整窗口宽度时它会自动适配布局、重新排列网格项。我想给这种布局变化加动画效果。我知道现在推荐用withAnimation和.animation(Animation?, value: Equatable),但网格布局是基于容器自动调整的,不依赖我自己管理的变量。原来适配这种场景的.animation(Animation?)方法已经被弃用了,但目前还能正常运行。我需要维护一个windowWidth状态变量(通过窗口resize事件更新)来实现动画吗?有没有更优的方案?
原代码示例
import SwiftUI @main struct MacosPlaygroundApp: App { let colors: [Color] = [.red, .pink, .blue, .brown, .cyan, .gray, .green, .indigo, .orange, .purple] let gridItem = GridItem( .adaptive(minimum: 100, maximum: 100), spacing: 10, alignment: .center ) var body: some Scene { WindowGroup { ScrollView(.vertical, showsIndicators: false) { LazyVGrid(columns: [gridItem], alignment: .center, spacing: 10) { ForEach(colors, id: \.self) { color in color .contentShape(Rectangle()) .cornerRadius(4) .frame(width: 100, height: 100) } }.animation(.easeIn) } .frame(minWidth: 120, maxWidth: .infinity, minHeight: 120, maxHeight: .infinity) } } }
最优解决方案
不需要手动监听窗口resize事件,利用GeometryReader监听LazyVGrid所在容器的宽度,将其作为.animation的value参数,即可让布局变化触发合规的动画效果,完全符合SwiftUI现代动画规范。
修改后的代码示例
import SwiftUI @main struct MacosPlaygroundApp: App { let colors: [Color] = [.red, .pink, .blue, .brown, .cyan, .gray, .green, .indigo, .orange, .purple] let gridItem = GridItem( .adaptive(minimum: 100, maximum: 100), spacing: 10, alignment: .center ) var body: some Scene { WindowGroup { ScrollView(.vertical, showsIndicators: false) { GeometryReader { geometry in LazyVGrid(columns: [gridItem], alignment: .center, spacing: 10) { ForEach(colors, id: \.self) { color in color .contentShape(Rectangle()) .cornerRadius(4) .frame(width: 100, height: 100) } } // 绑定容器宽度作为动画触发值,仅当宽度变化时触发动画 .animation(.easeIn, value: geometry.size.width) } } .frame(minWidth: 120, maxWidth: .infinity, minHeight: 120, maxHeight: .infinity) } } }
方案优势
- 无需手动处理窗口resize事件,
GeometryReader会自动感知容器尺寸变化 - 使用带
value参数的.animationAPI,完全符合SwiftUI最新规范,规避弃用API的兼容性风险 - 动画触发精准,仅在容器宽度变化时触发布局动画,避免不必要的UI异动
不推荐使用弃用API的原因
虽然.animation(Animation?)目前仍能运行,但它已被标记为弃用,未来SwiftUI版本可能移除该API,导致代码失效。此外,不带value的动画可能在无关状态变化时触发,引发意外的UI行为。
内容的提问来源于stack exchange,提问作者bzyr
相关产品推荐
相关产品推荐

