SwiftUI-手势
2020-07-12 本文已影响0人
否极泰来_L
SwiftUI为视图提供了许多手势,比如:
单击onTapGesture()
多击onTapGesture(count:)
长按onLongPressGesture()
放大MagnificationGesture()
旋转RotationGesture()
单击
Text("单击")
.onTapGesture {
print("单击🚀")
}
双击
Text("双击")
.onTapGesture(count: 2) {
print("双击🚀")
}
长按
长按相比单击手势复杂一点,是可以定制的。例如,指定需要满足的最少时长和最大时长。
Text("长按")
.onLongPressGesture(minimumDuration: 1, maximumDistance: 3, pressing: { (isProgress) in
print("长按进行中 -> \(isProgress)")
}) {
print("长按🚀")
}
长按进行中 -> true
长按进行中 -> false
长按🚀
对于更高级的手势,你需要使用gesture()
Modifier,并提供DragGesture
,LongPressGesture
, MagnificationGesture
,RotationGesture
或 TapGesture
。这些手势都有特定Modifier,最常用包括手势进行中onEnded ()
,已完成onEnded ()
,你可以在这里执行动作。
放大
struct ContentView: View {
@State private var currentAmount: CGFloat = 0
@State private var finalAmount: CGFloat = 1
var body: some View {
Text("放大")
.scaleEffect(finalAmount + currentAmount)
.gesture(
MagnificationGesture()
.onChanged { amount in
self.currentAmount = amount - 1
}
.onEnded { amount in
self.finalAmount += self.currentAmount
self.currentAmount = 0
}
)
}
}
旋转
struct ContentView: View {
@State private var currentAngle: Angle = .degrees(0)
@State private var finalAngle: Angle = .degrees(0)
var body: some View {
Text("旋转")
.rotationEffect(currentAmount + finalAmount)
.gesture(
RotationGesture()
.onChanged { angle in
self.currentAmount = angle
}
.onEnded { angle in
self.finalAmount += self.currentAmount
self.currentAmount = .degrees(0)
}
)
}
}
手势冲突
加入子视图和父视图同时有单击手势,点击子视图默认只会触发子视图的单击手势,我们可以使用highPriorityGesture ()
来强制父视图的手势优先。或者使用simultaneousGesture ()
来使父视图和子视图的手势同时触发。
struct ContentView: View {
var body: some View {
VStack {
Text("单击")
.onTapGesture {
print("单击🚀")
}
}
// simultaneousGesture(父视图和子视图同时触发) highPriorityGesture(高优先级,优先触发)
.simultaneousGesture(
TapGesture()
.onEnded { _ in
print("VStack🚀")
}
)
}
}
手势序列
SwiftUI还可以创建手势序列,序列中的手势之间存在引用,只有前一个手势成功识别之后才会被激活识别。
struct DragView: View {
// 圆被拖拽的偏移量
@State private var offset = CGSize.zero
// 圆是否正在被拖拽
@State private var isDragging = false
var body: some View {
// 拖拽手势更新偏移量,结束后更新偏移量和isDragging
let dragGesture = DragGesture()
.onChanged { (value) in
self.offset = value.translation
}
.onEnded { (_) in
withAnimation {
self.offset = .zero
self.isDragging = false
}
}
// 长按手势激活isDragging
let pressGesture = LongPressGesture()
.onEnded { (value) in
withAnimation {
self.isDragging = true
}
}
// 组合手势
let combined = pressGesture.sequenced(before: dragGesture)
return Circle()
.fill(Color.blue)
.frame(width: 80, height: 80)
.scaleEffect(isDragging ? 2 : 1)
.offset(offset)
.gesture(combined)
}
}
全部示例代码
ContentView
struct ContentView: View {
// 记录放大的值
@State private var currentAmount: CGFloat = 0
@State private var finalAmount: CGFloat = 1
// 记录旋转的值
@State private var currentAngle: Angle = .degrees(0)
@State private var finalAngle: Angle = .degrees(0)
var body: some View {
VStack {
VStack {
Text("单击")
.onTapGesture {
print("单击🚀")
}.padding(.top).padding(.horizontal)
Text("双击")
.onTapGesture(count: 2) {
print("双击🚀")
}.padding(.top)
Text("长按")
.onLongPressGesture(minimumDuration: 1, maximumDistance: 3, pressing: { (isProgress) in
print("长按进行中 -> \(isProgress)")
}) {
print("长按🚀")
}.padding(.top)
Text("放大")
.scaleEffect(finalAmount + currentAmount)
.gesture(
MagnificationGesture()
.onChanged({ (amount) in
self.currentAmount = amount - 1
})
.onEnded({ (amount) in
self.finalAmount += self.currentAmount
self.currentAmount = 0
})
).padding(.top)
Text("旋转")
.rotationEffect(finalAngle + currentAngle)
.gesture(
RotationGesture()
.onChanged({ (angle) in
self.currentAngle = angle
})
.onEnded({ (angle) in
self.finalAngle += self.currentAngle
self.currentAngle = .degrees(0)
})
).padding(.vertical)
}
.font(.title)
.background(Color.red)
// simultaneousGesture(父视图和子视图同时触发) highPriorityGesture(高优先级,优先触发)
.simultaneousGesture(
TapGesture()
.onEnded({ (_) in
print("VStack🚀")
})
)
// 拖拽view
DragView()
}
}
}
DragView
struct DragView: View {
// 手势序列
// 圆被拖拽的偏移量
@State private var offset = CGSize.zero
// 圆是否正在被拖拽
@State private var isDragging = false
var body: some View {
// 拖拽手势更新偏移量,结束后更新偏移量和isDragging
let dragGesture = DragGesture()
.onChanged { (value) in
self.offset = value.translation
}
.onEnded { (_) in
withAnimation {
self.offset = .zero
self.isDragging = false
}
}
// 长按手势激活isDragging
let pressGesture = LongPressGesture()
.onEnded { (value) in
withAnimation {
self.isDragging = true
}
}
// 组合手势
let combined = pressGesture.sequenced(before: dragGesture)
return Circle()
.fill(Color.blue)
.frame(width: 80, height: 80)
.scaleEffect(isDragging ? 2 : 1)
.offset(offset)
.gesture(combined)
}
}