mirror of
https://github.com/yattee/yattee.git
synced 2026-02-19 17:29:45 +00:00
78 lines
2.4 KiB
Swift
78 lines
2.4 KiB
Swift
//
|
|
// SwipeGesture.swift
|
|
// Yattee
|
|
//
|
|
// Custom pan gesture that filters horizontal swipes to avoid conflicts with ScrollView.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
#if os(iOS)
|
|
|
|
/// Value passed to gesture callbacks containing translation and velocity.
|
|
struct SwipeGestureValue {
|
|
var translation: CGSize = .zero
|
|
var velocity: CGSize = .zero
|
|
}
|
|
|
|
/// Custom pan gesture recognizer that only begins when horizontal velocity exceeds vertical.
|
|
/// This prevents conflicts with ScrollView vertical scrolling.
|
|
@available(iOS 18, *)
|
|
struct SwipeGesture: UIGestureRecognizerRepresentable {
|
|
var onBegan: () -> Void
|
|
var onChange: (SwipeGestureValue) -> Void
|
|
var onEnded: (SwipeGestureValue) -> Void
|
|
|
|
func makeCoordinator(converter: CoordinateSpaceConverter) -> Coordinator {
|
|
Coordinator()
|
|
}
|
|
|
|
func makeUIGestureRecognizer(context: Context) -> UIPanGestureRecognizer {
|
|
let gesture = UIPanGestureRecognizer()
|
|
gesture.delegate = context.coordinator
|
|
return gesture
|
|
}
|
|
|
|
func updateUIGestureRecognizer(_ recognizer: UIPanGestureRecognizer, context: Context) {}
|
|
|
|
func handleUIGestureRecognizerAction(_ recognizer: UIPanGestureRecognizer, context: Context) {
|
|
let state = recognizer.state
|
|
let translation = recognizer.translation(in: recognizer.view).toSize
|
|
let velocity = recognizer.velocity(in: recognizer.view).toSize
|
|
|
|
let gestureValue = SwipeGestureValue(translation: translation, velocity: velocity)
|
|
|
|
switch state {
|
|
case .began:
|
|
onBegan()
|
|
case .changed:
|
|
onChange(gestureValue)
|
|
case .ended, .cancelled:
|
|
onEnded(gestureValue)
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
|
|
class Coordinator: NSObject, UIGestureRecognizerDelegate {
|
|
/// Only begin the gesture when horizontal velocity exceeds vertical velocity.
|
|
/// This allows ScrollView to handle vertical scrolling while we handle horizontal swipes.
|
|
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
|
|
guard let panGesture = gestureRecognizer as? UIPanGestureRecognizer else {
|
|
return false
|
|
}
|
|
|
|
let velocity = panGesture.velocity(in: panGesture.view)
|
|
return abs(velocity.x) > abs(velocity.y)
|
|
}
|
|
}
|
|
}
|
|
|
|
private extension CGPoint {
|
|
var toSize: CGSize {
|
|
CGSize(width: x, height: y)
|
|
}
|
|
}
|
|
|
|
#endif
|