SwiftUI使用matchedGeometryEffect实现List转网格动画仅橙色正常问题
问题原因
- List 底层基于 UITableView 实现,默认开启裁剪特性,子视图移动超出 List 自身 frame 区域时,超出部分会被直接裁剪,导致看起来被遮挡在 List 下方。
- 切换视图时,即将消失的容器内子视图默认层级低于新出现的容器,色块在过渡过程中会被新视图盖住。你遇到的只有橙色色块正常,是因为橙色的动画路径刚好在重叠区域,不会触发裁剪也不会被层级遮挡。
- 额外的错误点:你重复给色块添加了
.animation(.easeIn)修饰符,和withAnimation重复定义动画规则,也可能引发动画异常。
修复方案
仅需三处修改即可解决问题:
- 给 List 添加
.clipped(false)修饰符,关闭默认裁剪 - 给所有使用
matchedGeometryEffect的色块添加.zIndex(1),统一提升过渡元素的层级 - 删除色块上重复添加的
.animation(.easeIn)修饰符
修改后的完整代码如下:
struct Colors: Identifiable{ var id = UUID() var col: Color } struct ContentView: View { @State var on = true @Namespace var ani var colors = [Colors(col: .green),Colors(col: .orange),Colors(col: .red)] var body: some View { VStack { if on { List{ ForEach(colors){col in col.col .matchedGeometryEffect(id: "\(col.id)", in: ani) .zIndex(1) } .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) } .listStyle(InsetGroupedListStyle()) .frame(height: 400) .clipped(false) } else { LazyVGrid(columns: [GridItem(.fixed(200)),GridItem(.fixed(200))], content: { ForEach(colors){col in col.col .matchedGeometryEffect(id: "\(col.id)", in: ani) .zIndex(1) } }) .frame(height: 400) } Button("toggle"){ withAnimation(.easeIn){ on.toggle() } } } } }
内容的提问来源于stack exchange,提问作者sheldor
相关产品推荐
相关产品推荐

