在 SwiftUI 中,.clipped()
是一个视图修饰符,用于将超出父视图边界的内容裁剪掉(类似于 CSS 的 overflow: hidden
)。以下是它的详细解析和使用指南:
一、核心功能
作用:强制将子视图内容限制在父视图的边界范围内,超出的部分会被裁剪。
swift
Rectangle()
.frame(width: 100, height: 100)
.overlay(
Circle()
.frame(width: 150, height: 150) // 超出矩形范围
)
.clipped() // 裁剪掉超出矩形的圆形部分
二、使用场景
1. 裁剪图片超出部分
swift
Image("landscape")
.resizable()
.aspectRatio(contentMode: .fill) // 填充可能导致溢出
.frame(width: 200, height: 200)
.clipped() // 确保图片不超出200x200范围
2. 组合圆角裁剪
swift
// 圆角 + 裁剪(常见于头像显示)
Image("avatar")
.resizable()
.scaledToFill()
.frame(width: 100, height: 100)
.cornerRadius(50) // 或 .clipShape(Circle())
.clipped() // 双重保障
3. 限制动画范围
swift
Text("滑动效果")
.offset(x: isActive ? 50 : -50) // 水平滑动
.frame(width: 200)
.clipped() // 防止文字滑出可视区域
三、与类似修饰符对比
修饰符 | 作用 | 典型用例 |
---|---|---|
.clipped() |
硬性裁剪超出部分 | 图片/视图严格限界 |
.cornerRadius(_:) |
添加圆角(自动隐含裁剪) | 圆角头像 |
.clipShape(_:) |
用任意形状裁剪 | 自定义形状裁切 |
.mask(_:) |
通过透明度蒙版裁剪 | 渐变边缘效果 |
四、技术细节
-
性能影响:
- 裁剪操作会启用离屏渲染(Offscreen Rendering),在复杂视图中可能影响性能
- 对静态视图优化较少,对动画视图需谨慎使用
-
与ZStack的关系:
swiftZStack { Color.blue Text("内容") } .frame(width: 100, height: 100) .clipped() // 会裁剪ZStack内所有子视图
-
iOS/macOS差异:
- 在 macOS 中可能需要额外设置
compositingGroup()
确保裁剪生效
- 在 macOS 中可能需要额外设置
五、进阶用法
1. 自定义裁剪形状
swift
// 用三角形裁剪
Image("pattern")
.clipShape(
Path { path in
path.move(to: CGPoint(x: 50, y: 0))
path.addLine(to: CGPoint(x: 100, y: 100))
path.addLine(to: CGPoint(x: 0, y: 100))
path.closeSubpath()
}
)
2. 动态裁剪
swift
@State private var clipAmount: CGFloat = 0.5
Image("texture")
.resizable()
.frame(width: 200, height: 200)
.mask(
Rectangle() // 蒙版控制可见区域
.frame(height: 200 * clipAmount)
)
常见问题
Q:为什么加了 .cornerRadius
还要用 .clipped()
?
A:某些情况下(如使用 offset
或 scaleEffect
),圆角裁剪可能失效,此时需要显式添加 .clipped()
确保效果。
Q:如何实现只裁剪顶部边缘?
A:组合使用 mask
:
swift
.mask(
VStack(spacing: 0) {
Rectangle()
.frame(height: 50) // 可见部分
Spacer() // 被裁剪部分
}
)