在 SwiftUI 中,.zIndex(_:)
是一个修饰符(Modifier),用于 控制视图在 Z 轴(前后层叠顺序)上的排列优先级。它决定了当多个视图重叠时,哪个视图显示在上层。以下是它的详细解析和实际应用指南:
1. 基本语法
swift
.zIndex(_ index: Double) // index: 层叠顺序值(越高越靠前)
- 参数 :
index
是一个Double
类型的值,默认为0
。- 值越大 ,视图越靠近用户(覆盖其他视图);值越小,视图越靠后(被其他视图覆盖)。
2. 核心功能
(1)基础层叠控制
swift
ZStack {
Circle()
.fill(Color.red)
.frame(width: 100, height: 100)
.zIndex(1) // 红色圆形在上层
Circle()
.fill(Color.blue)
.frame(width: 100, height: 100)
.offset(x: 30, y: 30) // 蓝色圆形部分重叠
.zIndex(0) // 蓝色圆形在下层
}
效果 :
红色圆形覆盖蓝色圆形(即使蓝色圆形在代码中后声明)。
(2)动态调整层叠顺序
swift
@State private var isOnTop = false
ZStack {
Rectangle()
.fill(isOnTop ? Color.gray : Color.green)
.frame(width: 200, height: 200)
.zIndex(isOnTop ? 0 : 1) // 动态切换层级
Button("切换层级") {
isOnTop.toggle()
}
.zIndex(2) // 按钮始终在最上层
}
3. 实际应用场景
场景 1:悬浮按钮(始终置顶)
swift
ZStack {
ScrollView {
// 长列表内容...
}
Button(action: {}) {
Image(systemName: "plus")
.padding()
.background(Circle().fill(Color.blue))
}
.zIndex(1) // 按钮悬浮在最上层
}
场景 2:卡片拖拽交互
swift
@State private var draggedCardIndex: Int?
ZStack {
ForEach(cards.indices, id: \.self) { index in
CardView(card: cards[index])
.zIndex(draggedCardIndex == index ? 1 : 0) // 拖拽的卡片置顶
.gesture(dragGesture(for: index))
}
}
场景 3:模态弹窗覆盖
swift
ZStack {
MainContentView() // 底层内容
if showModal {
Color.black.opacity(0.5)
.ignoresSafeArea()
.zIndex(1) // 半透明遮罩
ModalView()
.zIndex(2) // 弹窗内容在最上层
}
}
4. 与其他修饰符的关系
修饰符 | 作用 | 与 .zIndex 的区别 |
---|---|---|
.offset() |
调整视图位置 | 不改变层叠顺序 |
.overlay() |
添加覆盖层 | 自动置于原视图上层,但无法全局控制 |
.background() |
添加背景层 | 自动置于原视图下层 |
5. 注意事项
-
仅在相同容器内有效
.zIndex
只对同一父容器(如ZStack
、overlay
)内的子视图 生效。不同容器的视图无法直接比较zIndex
。 -
默认顺序规则
- 未指定
zIndex
时,视图按代码声明顺序层叠(后声明的在上层)。 - 指定
zIndex
后,优先级高于声明顺序。
- 未指定
-
性能优化
- 避免频繁动态修改
zIndex
(可能触发不必要的重绘)。 - 对静态层叠结构,尽量提前固定
zIndex
。
- 避免频繁动态修改
6. 完整代码示例
动态卡片层叠
swift
struct CardStackView: View {
@State private var cards = [
Card(color: .red, zIndex: 0),
Card(color: .green, zIndex: 0),
Card(color: .blue, zIndex: 0)
]
var body: some View {
ZStack {
ForEach(cards.indices, id: \.self) { index in
RoundedRectangle(cornerRadius: 10)
.fill(cards[index].color)
.frame(width: 200, height: 150)
.offset(x: CGFloat(index) * 20, y: CGFloat(index) * 20)
.zIndex(Double(cards[index].zIndex))
.onTapGesture {
// 点击时将卡片置顶
cards[index].zIndex = 1
withAnimation {
cards.indices.filter { $0 != index }.forEach {
cards[$0].zIndex = 0
}
}
}
}
}
}
}
struct Card {
let color: Color
var zIndex: Int
}
总结
功能 | 代码示例 |
---|---|
强制置顶 | .zIndex(1) |
动态层叠 | .zIndex(isActive ? 2 : 0) |
悬浮按钮 | Button(...).zIndex(999) |
核心用途 :
✅ 控制视图覆盖关系(如弹窗、悬浮按钮)
✅ 实现交互式层叠(如拖拽卡片、轮播图)
✅ 优化视觉层次(确保关键内容可见)
通过合理使用 .zIndex
,可以精准控制界面元素的显示优先级! 🎯