Как я могу зафиксировать, какое направление выполняется с помощью UIPanGestureRecognizer?
Хорошо, поэтому я просматривал почти все варианты под солнцем для захвата жестов с несколькими касаниями, и я наконец пришел в полный круг и вернулся в UIPanGestureRecognizer.
Функциональность, которую я хочу, очень проста. У меня настроен жест двух пальцев, и я хочу, чтобы можно было перемешать некоторые изображения в зависимости от количества пикселей, которые я перемещаю. У меня все получилось хорошо, но я хочу, чтобы у меня была возможность захватить, если жест панорамы REVERSED.
Есть ли встроенный способ, который я просто не вижу, чтобы обнаружить возврат к жесту? Должен ли я хранить исходную отправную точку, затем отслеживать конечную точку, а затем видеть, куда они двигаются после этого, и se, если она меньше начальной конечной точки, а затем наоборот? Я вижу, что это работает, но я надеюсь, что есть более элегантное решение!
Спасибо
EDIT:
Ниже приведен метод, с помощью которого распознаватель настроен на срабатывание. Его немного взломать, но он работает:
-(void) throttle:(UIGestureRecognizer *) recognize{
throttleCounter ++;
if(throttleCounter == 6){
throttleCounter = 0;
[self nextPic:nil];
}
UIPanGestureRecognizer *panGesture = (UIPanGestureRecognizer *) recognize;
UIView *view = recognize.view;
if(panGesture.state == UIGestureRecognizerStateBegan){
CGPoint translation = [panGesture translationInView:view.superview];
NSLog(@"X: %f, Y:%f", translation.x, translation.y);
}else if(panGesture.state == UIGestureRecognizerStateEnded){
CGPoint translation = [panGesture translationInView:view.superview];
NSLog(@"X: %f, Y:%f", translation.x, translation.y);
}
}
Я только что дошел до того момента, когда я начну пытаться отслеживать различия между значениями..., чтобы попытаться определить, как они панорамируются.
Ответы
Ответ 1
В UIPanGestureRecognizer вы можете использовать -velocityInView:, чтобы получить скорость пальцев во время распознавания жестов.
Если вы хотите сделать что-то одно в кастрюле справа и, например, одну вещь на панели слева, вы можете сделать что-то вроде:
- (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer
{
CGPoint velocity = [gestureRecognizer velocityInView:yourView];
if(velocity.x > 0)
{
NSLog(@"gesture went right");
}
else
{
NSLog(@"gesture went left");
}
}
Если вы буквально хотите обнаружить разворот, так как вы хотите сравнить новую скорость со старой и посмотреть, находится ли она в противоположном направлении - в зависимости от того, что может быть - вы могли бы сделать:
// assuming lastGestureVelocity is a class variable...
- (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer
{
CGPoint velocity = [gestureRecognizer velocityInView:yourView];
if(velocity.x*lastGestureVelocity.x + velocity.y*lastGestureVelocity.y > 0)
{
NSLog(@"gesture went in the same direction");
}
else
{
NSLog(@"gesture went in the opposite direction");
}
lastGestureVelocity = velocity;
}
Умножьте и добавьте вещь может выглядеть немного странно. На самом деле это точечный продукт, но будьте уверены, что это будет положительное число, если жесты находятся в одном направлении, опустившись до 0, если они находятся точно под прямым углом, а затем становятся отрицательным числом, если они находятся в противоположном направление.
Ответ 2
Здесь легко обнаружить до начала распознавания жестов:
public override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
guard let panRecognizer = gestureRecognizer as? UIPanGestureRecognizer else {
return super.gestureRecognizerShouldBegin(gestureRecognizer)
}
// Ensure it a horizontal drag
let velocity = panRecognizer.velocity(in: self)
if abs(velocity.y) > abs(velocity.x) {
return false
}
return true
}
Если требуется только перетаскивание по вертикали, вы можете переключить x
и y
.
Ответ 3
Этот код от Сергея Катранюка сработал лучше для меня.
https://github.com/serp1412/LazyTransitions
func addPanGestureRecognizers() {
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(respondToSwipeGesture(gesture:)))
self.view.addGestureRecognizer(panGesture)
}
func respondToSwipeGesture(gesture: UIGestureRecognizer){
if let swipeGesture = gesture as? UIPanGestureRecognizer{
switch gesture.state {
case .began:
print("began")
case .ended:
print("ended")
switch swipeGesture.direction{
case .rightToLeft:
print("rightToLeft")
case .leftToRight:
print("leftToRight")
case .topToBottom:
print("topToBottom")
case .bottomToTop:
print("bottomToTop")
default:
print("default")
}
default: break
}
}
}
//Расширения
import Foundation
import UIKit
public enum UIPanGestureRecognizerDirection {
case undefined
case bottomToTop
case topToBottom
case rightToLeft
case leftToRight
}
public enum TransitionOrientation {
case unknown
case topToBottom
case bottomToTop
case leftToRight
case rightToLeft
}
extension UIPanGestureRecognizer {
public var direction: UIPanGestureRecognizerDirection {
let velocity = self.velocity(in: view)
let isVertical = fabs(velocity.y) > fabs(velocity.x)
var direction: UIPanGestureRecognizerDirection
if isVertical {
direction = velocity.y > 0 ? .topToBottom : .bottomToTop
} else {
direction = velocity.x > 0 ? .leftToRight : .rightToLeft
}
return direction
}
public func isQuickSwipe(for orientation: TransitionOrientation) -> Bool {
let velocity = self.velocity(in: view)
return isQuickSwipeForVelocity(velocity, for: orientation)
}
private func isQuickSwipeForVelocity(_ velocity: CGPoint, for orientation: TransitionOrientation) -> Bool {
switch orientation {
case .unknown : return false
case .topToBottom : return velocity.y > 1000
case .bottomToTop : return velocity.y < -1000
case .leftToRight : return velocity.x > 1000
case .rightToLeft : return velocity.x < -1000
}
}
}
extension UIPanGestureRecognizer {
typealias GestureHandlingTuple = (gesture: UIPanGestureRecognizer? , handle: (UIPanGestureRecognizer) -> ())
fileprivate static var handlers = [GestureHandlingTuple]()
public convenience init(gestureHandle: @escaping (UIPanGestureRecognizer) -> ()) {
self.init()
UIPanGestureRecognizer.cleanup()
set(gestureHandle: gestureHandle)
}
public func set(gestureHandle: @escaping (UIPanGestureRecognizer) -> ()) {
weak var weakSelf = self
let tuple = (weakSelf, gestureHandle)
UIPanGestureRecognizer.handlers.append(tuple)
addTarget(self, action: #selector(handleGesture))
}
fileprivate static func cleanup() {
handlers = handlers.filter { $0.0?.view != nil }
}
@objc private func handleGesture(_ gesture: UIPanGestureRecognizer) {
let handleTuples = UIPanGestureRecognizer.handlers.filter{ $0.gesture === self }
handleTuples.forEach { $0.handle(gesture)}
}
}
extension UIPanGestureRecognizerDirection {
public var orientation: TransitionOrientation {
switch self {
case .rightToLeft: return .rightToLeft
case .leftToRight: return .leftToRight
case .bottomToTop: return .bottomToTop
case .topToBottom: return .topToBottom
default: return .unknown
}
}
}
extension UIPanGestureRecognizerDirection {
public var isHorizontal: Bool {
switch self {
case .rightToLeft, .leftToRight:
return true
default:
return false
}
}
}