如何让SwiftUI的Matched Geometry Effect实现裁剪到无裁剪的平滑过渡
实现裁剪视图到无裁剪状态的Matched Geometry平滑过渡
直接在两个视图中分别添加/移除clipShape无法让裁剪状态参与Matched Geometry动画,因为该效果默认仅同步视图的位置、尺寸等几何属性,不会处理裁剪这类修饰符的状态变化。要实现平滑过渡,需要让裁剪参数成为可动画的状态变量,随视图展开/收起逐步变化。
修改方案
- 新增状态变量控制裁剪圆角半径,根据视图展开状态切换值:未展开时设为视图尺寸的一半(实现圆形裁剪),展开时设为0(无裁剪)。
- 将重复的图片视图合并为一个,通过状态变量控制尺寸和裁剪程度,避免冗余代码。
- 确保动画同时驱动尺寸变化和裁剪参数变化,让两个过渡同步进行。
修改后的代码
struct ContentView: View { @State private var show = false @Namespace var namespace // 初始裁剪半径为小视图的一半,实现圆形裁剪 @State private var clipRadius: CGFloat = 18.75 var body: some View { VStack { KFImage(URL(string: "https://dfstudio-d420.kxcdn.com/wordpress/wp-content/uploads/2019/06/digital_camera_photo-1080x675.jpg")) .resizable() .aspectRatio(contentMode: .fill) // 先应用Matched Geometry Effect,确保几何属性同步 .matchedGeometryEffect(id: "squareAnim", in: namespace) // 根据状态切换视图尺寸 .frame(width: show ? 150 : 37.5, height: show ? 150 : 37.5) // 用状态变量控制裁剪程度 .clipShape(RoundedRectangle(cornerRadius: clipRadius)) .onTapGesture { withAnimation(.easeInOut) { show.toggle() // 同步更新裁剪半径 clipRadius = show ? 0 : 18.75 } } } // 添加半透明背景,点击可关闭展开视图 .overlay { if show { Color.black.opacity(0.5) .ignoresSafeArea() .onTapGesture { withAnimation(.easeInOut) { show.toggle() clipRadius = 18.75 } } } } } }
关键说明
- 裁剪参数
clipRadius随动画平滑变化,让裁剪状态和视图尺寸的过渡同步完成,实现自然的动画效果。 - 如果需要从矩形(圆角矩形)过渡到无裁剪,只需调整初始
clipRadius为对应圆角值即可(比如设为8,展开时设为0)。 - 合并重复的图片视图后,Matched Geometry Effect能更可靠地同步视图的几何属性,避免动画异常。
内容的提问来源于stack exchange,提问作者Ahmed Zaidan
相关产品推荐
相关产品推荐

