SwiftUI弹簧动画中如何允许列表内容溢出以避免裁剪?
SwiftUI弹簧动画中如何允许列表内容溢出以避免裁剪?
嗨,我来帮你搞定这个问题~你遇到的情况是SwiftUI的List默认自带裁剪行为,当内容在弹簧动画里放大时,超出List边界的部分就会被自动切掉,这就是你看到文本边框被裁掉的原因。
给你几个实用的解决办法,你可以根据自己的场景选:
方法一:关闭List的自动裁剪(最简单直接)
只需要给你的List加上.clipped(false)修饰符就行,它会告诉SwiftUI不要裁剪超出List布局范围的内容,这样动画过程中放大的内容就能完整显示了。如果你的List不需要滚动(比如这个场景里内容不多),还可以再加个.scrollDisabled(true),避免动画时不小心触发滚动,体验更丝滑。
修改后的代码示例:
struct ContentView: View { @State var big = false @Namespace private var firstNamespace @Namespace private var secondNamespace var body: some View { VStack { Button { withAnimation(.spring(response: 2, dampingFraction: 0.2)) { big.toggle() } } label: { Text("Resize") } List{ ZStack { if big { VStack { Text("first") .frame(maxWidth: .infinity, maxHeight: .infinity) .matchedGeometryEffect(id: "first", in: firstNamespace) Text("second") .frame(maxWidth: .infinity, maxHeight: .infinity) .matchedGeometryEffect(id: "second", in: secondNamespace) } } else { HStack { Text("first") .frame(maxWidth: .infinity, maxHeight: .infinity) .matchedGeometryEffect(id: "first", in: firstNamespace) Text("second") .frame(maxWidth: .infinity, maxHeight: .infinity) .matchedGeometryEffect(id: "second", in: secondNamespace) } } } } .clipped(false) // 关键:关闭List的自动裁剪 .scrollDisabled(true) // 可选:不需要滚动时添加 } } }
方法二:用ScrollView+LazyVStack替代List
List本身有不少内置的布局限制,如果你不需要List的一些特殊功能(比如侧滑删除、分组样式),可以换成ScrollView包裹LazyVStack的组合,因为ScrollView默认不会裁剪超出的内容,从根源上避免这个问题。
示例代码大概是这样:
struct ContentView: View { @State var big = false @Namespace private var firstNamespace @Namespace private var secondNamespace var body: some View { VStack { Button { withAnimation(.spring(response: 2, dampingFraction: 0.2)) { big.toggle() } } label: { Text("Resize") } ScrollView { LazyVStack { ZStack { if big { VStack { Text("first") .frame(maxWidth: .infinity, maxHeight: .infinity) .matchedGeometryEffect(id: "first", in: firstNamespace) Text("second") .frame(maxWidth: .infinity, maxHeight: .infinity) .matchedGeometryEffect(id: "second", in: secondNamespace) } } else { HStack { Text("first") .frame(maxWidth: .infinity, maxHeight: .infinity) .matchedGeometryEffect(id: "first", in: firstNamespace) Text("second") .frame(maxWidth: .infinity, maxHeight: .infinity) .matchedGeometryEffect(id: "second", in: secondNamespace) } } } } } } } }
你可以试试这两种方法,第一种更适合想保留List原有功能的场景,第二种则更灵活自由~
备注:内容来源于stack exchange,提问作者Oskar Persson
相关产品推荐
相关产品推荐

