自定义手势识别器不使用UIImageView

时间:2012-04-18 15:12:42

标签: ios uiimageview uigesturerecognizer

我正在使用dysternis » An one finger rotation gesture recognizer实现自定义一个手指旋转手势,图像旋转正常,但我有另一个按钮,点击它有一些事件,但现在我必须触摸拖动按钮解雇事件。

然后我尝试将相同的手势识别器添加到图像视图中,但它看起来不太好。它没有正确旋转图像。有没有什么需要改变或者我遗失了什么。

这是我的代码的编辑版本。请注意,我已启用用户与UIImageView的交互。

在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

在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

在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

1 个答案:

答案 0 :(得分:0)

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