简体   繁体   中英

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.

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.

In OneFingerRotationGestureRecognizer.h file:

#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

#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:

@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 ,现在效果很好。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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