Обнаружение направления жестов PAN в iOS
В моем приложении есть просмотр изображения. Я добавляю жест PAN к этому представлению изображения.
Это нормально работает.
Изображение находится в ландшафтном режиме.
Я хочу увеличить счетчик в метке, пока пользовательская панорама вправо и уменьшит этот счет, пока пользовательская панорама влево.
Я много искал, но не нашел для этого решения.
Может ли кто-нибудь помочь мне определить направление, в котором пользователь панорамирует (влево/вправо)?
Ответы
Ответ 1
В целевом селекторе распознавателя жестов используйте - (CGPoint)velocityInView:(UIView *)view;
:
- (void)panRecognized:(UIPanGestureRecognizer *)rec
{
CGPoint vel = [rec velocityInView:self.view];
if (vel.x > 0)
{
// user dragged towards the right
counter++;
}
else
{
// user dragged towards the left
counter--;
}
}
P.s.: Я не знал об этом методе до прибл. За 3 минуты до этого. Одним из первых хитов Google была официальная документация Apple.
Ответ 2
Что-то вроде этого:
- (void)pan:(UIPanGestureRecognizer *)sender
{
typedef NS_ENUM(NSUInteger, UIPanGestureRecognizerDirection) {
UIPanGestureRecognizerDirectionUndefined,
UIPanGestureRecognizerDirectionUp,
UIPanGestureRecognizerDirectionDown,
UIPanGestureRecognizerDirectionLeft,
UIPanGestureRecognizerDirectionRight
};
static UIPanGestureRecognizerDirection direction = UIPanGestureRecognizerDirectionUndefined;
switch (sender.state) {
case UIGestureRecognizerStateBegan: {
if (direction == UIPanGestureRecognizerDirectionUndefined) {
CGPoint velocity = [sender velocityInView:recognizer.view];
BOOL isVerticalGesture = fabs(velocity.y) > fabs(velocity.x);
if (isVerticalGesture) {
if (velocity.y > 0) {
direction = UIPanGestureRecognizerDirectionDown;
} else {
direction = UIPanGestureRecognizerDirectionUp;
}
}
else {
if (velocity.x > 0) {
direction = UIPanGestureRecognizerDirectionRight;
} else {
direction = UIPanGestureRecognizerDirectionLeft;
}
}
}
break;
}
case UIGestureRecognizerStateChanged: {
switch (direction) {
case UIPanGestureRecognizerDirectionUp: {
[self handleUpwardsGesture:sender];
break;
}
case UIPanGestureRecognizerDirectionDown: {
[self handleDownwardsGesture:sender];
break;
}
case UIPanGestureRecognizerDirectionLeft: {
[self handleLeftGesture:sender];
break;
}
case UIPanGestureRecognizerDirectionRight: {
[self handleRightGesture:sender];
break;
}
default: {
break;
}
}
}
case UIGestureRecognizerStateEnded: {
direction = UIPanGestureRecognizerDirectionUndefined;
break;
}
default:
break;
}
}
- (void)handleUpwardsGesture:(UIPanGestureRecognizer *)sender
{
NSLog(@"Up");
}
- (void)handleDownwardsGesture:(UIPanGestureRecognizer *)sender
{
NSLog(@"Down");
}
- (void)handleLeftGesture:(UIPanGestureRecognizer *)sender
{
NSLog(@"Left");
}
- (void)handleRightGesture:(UIPanGestureRecognizer *)sender
{
NSLog(@"Right");
}
Ответ 3
Мой предыдущий ответ в Swift
public enum Direction: Int {
case Up
case Down
case Left
case Right
public var isX: Bool { return self == .Left || self == .Right }
public var isY: Bool { return !isX }
}
public extension UIPanGestureRecognizer {
public var direction: Direction? {
let velocity = velocityInView(view)
let vertical = fabs(velocity.y) > fabs(velocity.x)
switch (vertical, velocity.x, velocity.y) {
case (true, _, let y) where y < 0: return .Up
case (true, _, let y) where y > 0: return .Down
case (false, let x, _) where x > 0: return .Right
case (false, let x, _) where x < 0: return .Left
default: return nil
}
}
}
Ответ 4
Вот исправленная версия Swift 5 с примером использования:
public enum PanDirection: Int {
case up, down, left, right
public var isVertical: Bool { return [.up, .down].contains(self) }
public var isHorizontal: Bool { return !isVertical }
}
public extension UIPanGestureRecognizer {
var direction: PanDirection? {
let velocity = self.velocity(in: view)
let isVertical = abs(velocity.y) > abs(velocity.x)
switch (isVertical, velocity.x, velocity.y) {
case (true, _, let y) where y < 0: return .up
case (true, _, let y) where y > 0: return .down
case (false, let x, _) where x > 0: return .right
case (false, let x, _) where x < 0: return .left
default: return nil
}
}
}
@IBAction func pan(_ recognizer: UIPanGestureRecognizer) {
if let direction = recognizer.direction {
if direction.isVertical {
//do what you want when pan is vertical
} else if direction == .left {
//do what you want when pan is left
}
}
}
Ответ 5
Обратите внимание, что вышеприведенная версия Adam Swift содержит ошибку. .up должен возвращаться, если y <0, и .down должен возвращаться, если y> 0 (они обращены).
Так:
//MARK: - Direction
internal enum Direction {
case up
case down
case left
case right
}
//MARK: - UIPanGestureRecognizer
internal extension UIPanGestureRecognizer {
internal var direction: Direction? {
let velocity = velocityInView(view)
let isVertical = fabs(velocity.y) > fabs(velocity.x)
switch (isVertical, velocity.x, velocity.y) {
case (true, _, let y) where y < 0: return .up
case (true, _, let y) where y > 0: return .down
case (false, let x, _) where x > 0: return .right
case (false, let x, _) where x < 0: return .left
default: return nil
}
}
}
Ответ 6
Перепишите версию Адама Уэйт на Swift 3
public enum PanDirection: Int {
case up,
down,
left,
right
public var isX: Bool {
return self == .left || self == .right
}
public var isY: Bool {
return !isX
}
}
extension UIPanGestureRecognizer {
var direction: PanDirection? {
let velocity = self.velocity(in: view)
let vertical = fabs(velocity.y) > fabs(velocity.x)
switch (vertical, velocity.x, velocity.y) {
case (true, _, let y):
return y < 0 ? .up : .down
case (false, let x, _):
return x > 0 ? .right : .left
}
}
}