GestureState
的使用与场景
#
GestureState
是 SwiftUI 中一个专门用于捕获和管理手势状态的属性包装器(@GestureState
)。它适用于在 手势操作中临时存储状态,并能让手势操作在结束时自动重置状态值。
GestureState
常用于在以下场景:
- 临时存储手势的状态值(如拖动的偏移量、缩放的比例等)。
- 在手势进行的过程中动态响应并更新界面。
- 手势结束时,自动将状态重置,加速状态管理。
1. 使用场景 #
以下是一些常见场景,GestureState
会非常有用:
1.1 拖动手势(DragGesture
)
#
- 临时存储手势的偏移(例如手指拖动过程中的位移距离)。
- 动态更新视图的位置,展示拖动效果。
1.2 缩放手势(MagnificationGesture
)
#
- 临时存储手势的缩放比例。
- 动态调整视图的缩放倍数。
1.3 旋转手势(RotationGesture
)
#
- 临时存储旋转角度。
- 用户旋转图片或对象时,更新旋转角度。
1.4 组合手势(SimultaneousGesture
或 CombinedGesture
)
#
- 同时捕获多个手势,例如支持拖动和缩放,需要在手势结束时将状态恢复到初始值。
特点 #
- 与
@State
类似,但GestureState
在手势结束后会自动复位为初始值。 - 避免了手势数据需要重复重置的麻烦。
2. 语法与基本使用 #
GestureState
的基本用法包括:
- 用
@GestureState
定义一个变量,作为临时状态值。 - 配合 SwiftUI 手势(如
DragGesture
,MagnificationGesture
)实时更新状态。 - 手势结束后,
GestureState
会自动还原到初始状态。
基本语法 #
@GestureState var temporaryState: ValueType = initialValue
ValueType
:状态的类型,例如CGSize
(拖动的偏移量)、Double
(缩放比例或旋转角度)。initialValue
:手势未激活时的默认初始值。
3. 示例与实际应用 #
3.1 拖动手势(DragGesture
)
#
示例:用 GestureState
存储临时偏移量
#
下面的示例中,用户在拖动时动态移动一个视图。
import SwiftUI
struct DragGestureExample: View {
@GestureState private var dragOffset: CGSize = .zero // 临时存储拖动位移
@State private var finalOffset: CGSize = .zero // 最终视图位置
var body: some View {
Circle()
.fill(Color.blue)
.frame(width: 100, height: 100)
.offset(x: finalOffset.width + dragOffset.width, y: finalOffset.height + dragOffset.height) // 结合拖动的偏移
.gesture(
DragGesture()
.updating($dragOffset) { value, gestureState, _ in
// 创建 `dragOffset` 变化
gestureState = value.translation
}
.onEnded { value in
// 手势结束时更新最终偏移
finalOffset.width += value.translation.width
finalOffset.height += value.translation.height
}
)
}
}
执行流程:
@GestureState dragOffset
临时存储拖动的偏移。- 用户拖动过程中,
gesture.updating
实时更新状态至dragOffset
。 - 手势结束,偏移自动回归初始值(
dragOffset = .zero
),同时将最终偏移存储在finalOffset
中。
3.2 缩放手势(MagnificationGesture
)
#
示例:缩放视图 #
通过 GestureState
临时存储缩放比例,动态放大或缩小视图。
import SwiftUI
struct MagnificationGestureExample: View {
@GestureState private var magnificationValue: CGFloat = 1.0 // 临时存储缩放比例
@State private var scale: CGFloat = 1.0 // 最终缩放比例
var body: some View {
Image(systemName: "photo")
.resizable()
.scaledToFit()
.frame(width: 200, height: 200)
.scaleEffect(scale * magnificationValue) // 缩放效果
.gesture(
MagnificationGesture()
.updating($magnificationValue) { value, gestureState, _ in
gestureState = value // 临时更新缩放状态
}
.onEnded { value in
// 手势结束时,累积缩放比例
scale *= value
}
)
}
}
执行流程:
- 用户触发捏合手势时,
magnificationValue
存储缩放比例。 - 视图动态响应缩放比例变化。
- 手势结束时,
magnificationValue
自动复位为1.0
,记录的缩放累积到最终比例scale
。
3.3 旋转手势(RotationGesture
)
#
示例:旋转图片 #
通过 GestureState
存储临时旋转角度。
import SwiftUI
struct RotationGestureExample: View {
@GestureState private var rotationDegrees: Angle = .zero
@State private var finalRotation: Angle = .zero
var body: some View {
Image(systemName: "arrow.left.circle.fill")
.resizable()
.frame(width: 150, height: 150)
.rotationEffect(finalRotation + rotationDegrees) // 旋转效果
.gesture(
RotationGesture()
.updating($rotationDegrees) { value, gestureState, _ in
gestureState = value // 存储临时旋转角度
}
.onEnded { value in
// 累加旋转角度
finalRotation += value
}
)
}
}
3.4 组合手势:拖动 + 缩放 #
通过同时支持拖动和缩放手势,实现更复杂的交互。
struct CombinedGestureExample: View {
@GestureState private var dragOffset: CGSize = .zero
@GestureState private var magnification: CGFloat = 1.0
@State private var finalOffset: CGSize = .zero
@State private var currentScale: CGFloat = 1.0
var body: some View {
Circle()
.fill(Color.red)
.frame(width: 100, height: 100)
.offset(x: finalOffset.width + dragOffset.width, y: finalOffset.height + dragOffset.height)
.scaleEffect(currentScale * magnification) // 缩放效果
.gesture(
SimultaneousGesture( // 同时捕捉缩放和拖动
DragGesture()
.updating($dragOffset) { value, gestureState, _ in
gestureState = value.translation
}
.onEnded { value in
finalOffset.width += value.translation.width
finalOffset.height += value.translation.height
},
MagnificationGesture()
.updating($magnification) { value, gestureState, _ in
gestureState = value
}
.onEnded { value in
currentScale *= value
}
)
)
}
}
4. GestureState
和 @State
的区别
#
特性 | GestureState | @State |
---|---|---|
用途 | 临时存储手势状态,仅在手势过程中生效。 | 常规状态存储,贯穿整个组件生命周期。 |
状态重置 | 手势完成后状态会自动重置为初始值。 | 必须手动重置状态值。 |
常见场景 | 拖动、缩放、旋转等动态、临时的状态更新。 | 长期存储位置、颜色、大小等静态变量。 |
手势结合使用 | 通常用于 gesture.updating 更新临时状态。 | 通常与 gesture.onEnded 更新最终状态。 |
5. 总结 #
@GestureState
的主要特点和最佳使用场景:
- 特点:
- 临时状态存储,手势结束时自动清空。
- 适合处理短生命周期的状态。
- 最佳场景:
- 拖动(
DragGesture
)的角度或偏移。 - 缩放(
MagnificationGesture
)中的比例变化。 - 旋转(
RotationGesture
)中的角度变化。 - 多手势组合处理时,用作各个手势的临时数据容器。
- 拖动(