SwiftUI長押しを実装する際にonLongPressGestureやLongPressGestureを使用します。
これは通常、指定した時間長押しすると手を離さずとも実行されます。
今回はこれを手を離したタイミングで実行する方法を紹介します。
実装方法
LongPressGestureの前にgestureを追加してDragGestureを実装します。
DragGestureの中身は不要です。
こうする事でDragGestureが優先される為、DragGestureの判定が終わるまでLongPressGestureが実行されません。
DragGestureは指を離したタイミングで終わるので、LongPressGestureの実行も指を離すまで実行されません。
なお、DragGestureを後に実装するとLongPressGestureは通常通り動作します。
この場合はLongPressGestureが実行されるとDragGestureが実行されません。
SwiftUIではよくある事ですがModifierの順序には気をつけましょう。
サンプルコード
Textのgestureをつけたものを2つ用意しました。
もちろんonLongPressGestureはgesture(LongPressGesture())でも問題ありません。
動作の違いを確認してみてください。
struct SampleView: View {
var body: some View {
VStack {
Text("Pressing")
.padding()
.onLongPressGesture{
print("LongPress")
}
//LongPressGestureはどちらでも良い
// .gesture(LongPressGesture().onEnded{ _ in
// print("LongPress")
// })
.gesture(DragGesture().onEnded{ _ in
print("Drag")
})
Text("Release")
.padding()
.gesture(DragGesture().onEnded{ _ in
print("Drag")
})
.onLongPressGesture{
print("LongPress")
}
}
}
}
動画で違いを確認する
gestureの順序の違いがわかる動画を用意しました。
見やすいように色々追加していますが、やっている事は先程のコードと同様です。
おまけ
動画で使ったViewのコードです。
struct MovieView: View {
@State var text = "None"
var body: some View {
NavigationStack {
VStack {
Spacer()
Text("LongPressGestureの\n実行タイミングを変える")
.multilineTextAlignment(.center)
.font(.title2)
Spacer()
VStack {
Text("Pressing")
.font(.title)
.foregroundColor(.white)
.frame(width: 150)
.padding()
.background(.blue)
.cornerRadius(10)
.gesture(LongPressGesture().onEnded{ _ in
text = "LongPress"
setNone()
})
.gesture(DragGesture().onEnded{ _ in
text = "Drag"
setNone()
})
.padding()
Text("Release")
.font(.title)
.foregroundColor(.white)
.frame(width: 150)
.padding()
.background(.blue)
.cornerRadius(10)
.gesture(DragGesture().onEnded{ _ in
text = "Drag"
setNone()
})
.gesture(LongPressGesture().onEnded{ _ in
text = "LongPress"
setNone()
})
.padding()
}
Spacer()
VStack {
HStack {
Text("Status")
.font(.title3)
Spacer()
}
Text(text)
.font(.title)
}.frame(width: 150)
Spacer()
}.navigationTitle("LongPressGesture")
}
}
func setNone(){
Task{
try? await Task.sleep(nanoseconds: 2 * 1000 * 1000 * 1000)
await MainActor.run{
text = "None"
}
}
}
}
コメント