简体   繁体   English

自定义手势识别器不能与UIImageView一起使用

[英]Custom Gesture Recognizer not working with UIImageView

I am implementing a custom one finger rotation gesture using dysternis » An one finger rotation gesture recognizer and the image is rotating fine with this, but I have another button with some event on it's click, but now I have to touch drag on the button to fire the event. 我正在使用dysternis实现自定义的单指旋转手势»单指旋转手势识别器 ,图像与此同时旋转良好,但是我单击了另一个带有某些事件的按钮,但是现在我必须触摸该按钮上的拖动触发事件。

I have then tried to add the same gesture recognizer only to the image view, but it don't seem good. 然后,我试图仅将相同的手势识别器添加到图像视图中,但这似乎并不好。 It is not rotating the image properly. 它无法正确旋转图像。 Is there any thing that is needed to be changed or I am missing something. 有什么需要更改的东西,或者我错过了什么。

Here is the edited version with my code. 这是带有我的代码的编辑版本。 Please note that I have enabled the user interaction with the UIImageView. 请注意,我已经启用了与UIImageView的用户交互。

In OneFingerRotationGestureRecognizer.h file: 在OneFingerRotationGestureRecognizer.h文件中:

#import <Foundation/Foundation.h>
#import <UIKit/UIGestureRecognizerSubclass.h>

@protocol OneFingerRotationGestureRecognizerDelegate <NSObject>
@optional
- (void) rotation: (CGFloat) angle;
- (void) finalAngle: (CGFloat) angle;
@end

@interface OneFingerRotationGestureRecognizer : UIGestureRecognizer
{
CGPoint midPoint;
CGFloat innerRadius;
CGFloat outerRadius;
CGFloat cumulatedAngle;
id <OneFingerRotationGestureRecognizerDelegate> target;
}

- (id) initWithMidPoint: (CGPoint) midPoint
            innerRadius: (CGFloat) innerRadius
            outerRadius: (CGFloat) outerRadius
                 target: (id) target;
- (void)reset;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

@end

In OneFingerRotationGestureRecognizer.m file 在OneFingerRotationGestureRecognizer.m文件中

#include <math.h>

#import "OneFingerRotationGestureRecognizer.h"

@implementation OneFingerRotationGestureRecognizer

// private helper functions
CGFloat distanceBetweenPoints(CGPoint point1, CGPoint point2);
CGFloat angleBetweenLinesInDegrees(CGPoint beginLineA,
                                   CGPoint endLineA,
                                   CGPoint beginLineB,
                                   CGPoint endLineB);

- (id) initWithMidPoint: (CGPoint) _midPoint
            innerRadius: (CGFloat) _innerRadius
            outerRadius: (CGFloat) _outerRadius
                 target: (id <OneFingerRotationGestureRecognizerDelegate>) _target
{
    if ((self = [super initWithTarget: _target action: nil]))
    {
        midPoint    = _midPoint;
        innerRadius = _innerRadius;
        outerRadius = _outerRadius;
        target      = _target;
    }
    return self;
}

/** Calculates the distance between point1 and point 2. */
CGFloat distanceBetweenPoints(CGPoint point1, CGPoint point2)
{
    CGFloat dx = point1.x - point2.x;
    CGFloat dy = point1.y - point2.y;
    return sqrt(dx*dx + dy*dy);
}

CGFloat angleBetweenLinesInDegrees(CGPoint beginLineA,
                                   CGPoint endLineA,
                                   CGPoint beginLineB,
                                   CGPoint endLineB)
{
    CGFloat a = endLineA.x - beginLineA.x;
    CGFloat b = endLineA.y - beginLineA.y;
    CGFloat c = endLineB.x - beginLineB.x;
    CGFloat d = endLineB.y - beginLineB.y;

    CGFloat atanA = atan2(a, b);
    CGFloat atanB = atan2(c, d);

    // convert radiants to degrees
    return (atanA - atanB) * 180 / M_PI;
 }

 #pragma mark - UIGestureRecognizer implementation

 - (void)reset
 {
    [super reset];
    cumulatedAngle = 0;
 }

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
 {
    [super touchesBegan:touches withEvent:event];

    if ([touches count] != 1)
    {
        self.state = UIGestureRecognizerStateFailed;

        return;
    }
 }

 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
 {
    [super touchesMoved:touches withEvent:event];

    if (self.state == UIGestureRecognizerStateFailed) return;

    CGPoint nowPoint  = [[touches anyObject] locationInView: self.view];
    CGPoint prevPoint = [[touches anyObject] previousLocationInView: self.view];

    // make sure the new point is within the area
    CGFloat distance = distanceBetweenPoints(midPoint, nowPoint);
    if (   innerRadius <= distance
        && distance    <= outerRadius)
    {
        // calculate rotation angle between two points
        CGFloat angle = angleBetweenLinesInDegrees(midPoint, prevPoint, midPoint, nowPoint);

        // fix value, if the 12 o'clock position is between prevPoint and nowPoint
        if (angle > 180)
        {
           angle -= 360;
        }
        else if (angle < -180)
        {
           angle += 360;
        }

        // sum up single steps
        cumulatedAngle += angle;

        // call delegate
        if ([target respondsToSelector: @selector(rotation:)])
        {
           [target rotation:angle];
        }
     }  
     else
     {
        // finger moved outside the area
        self.state = UIGestureRecognizerStateFailed;
     }
  }

  - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
  {
     [super touchesEnded:touches withEvent:event];

     if (self.state == UIGestureRecognizerStatePossible)
     {
        self.state = UIGestureRecognizerStateRecognized;

        if ([target respondsToSelector: @selector(finalAngle:)])
        {
            [target finalAngle:cumulatedAngle];
        }
     }
     else
     {
        self.state = UIGestureRecognizerStateFailed;
     }

     cumulatedAngle = 0;
  }

  - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
  {
     [super touchesCancelled:touches withEvent:event];

     self.state = UIGestureRecognizerStateFailed;
     cumulatedAngle = 0;
  }

  @end

In View Contoller.m file: 在View Contoller.m文件中:

@interface deviceDetailViewController ()
{
  @private CGFloat imageAngle;
  @private OneFingerRotationGestureRecognizer *gestureRecognizer;
}

- (void) updateTextDisplay;
- (void) setupGestureRecognizer;
@end

@implementation deviceDetailViewController
- (void)viewDidLoad
{
    [self setupGestureRecognizer];

    [super viewDidLoad];
}
#pragma mark - CircularGestureRecognizerDelegate protocol

- (void) rotation: (CGFloat) angle
{
    // calculate rotation angle
    imageAngle += angle;
    if (imageAngle > 360)
        imageAngle -= 360;
    else if (imageAngle < -360)
        imageAngle += 360;

    // rotate image and update text field
    deviceRotator.transform = CGAffineTransformMakeRotation(imageAngle *  M_PI / 180);

    [self updateTextDisplay];
 }

 - (void) finalAngle: (CGFloat) angle
 {
    // circular gesture ended, update text field
    [self updateTextDisplay];
 }

 #pragma mark - Helper methods

// Updates the text field with the current rotation angle.
- (void) updateTextDisplay
{
    textDisplay.text = [NSString stringWithFormat: @"\u03b1 = %.2f", imageAngle];
}

// Addes gesture recognizer to the view (or any other parent view of image. Calculates        midPoint
// and radius, based on the image position and dimension.
- (void) setupGestureRecognizer
{
    // calculate center and radius of the control
    CGPoint midPoint = CGPointMake(deviceRotator.frame.origin.x + deviceRotator.frame.size.width / 2,deviceRotator.frame.origin.y +   deviceRotator.frame.size.height / 2);
    CGFloat outRadius = deviceRotator.frame.size.width / 2;

    // outRadius / 3 is arbitrary, just choose something >> 0 to avoid strange 
    // effects when touching the control near of it's center
    gestureRecognizer = [[OneFingerRotationGestureRecognizer alloc] initWithMidPoint: midPoint
                                                                         innerRadius: outRadius / 3 
                                                                         outerRadius: outRadius
                                                                              target: self];
    //    [self.deviceRotator addGestureRecognizer:gestureRecognizer];
   [self.view addGestureRecognizer: gestureRecognizer];
}
@end

我已经将此自定义手势添加到整个视图中,但是对按钮本身实现了另一个UITapGestureRecognizer ,现在效果很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM