簡體   English   中英

自定義手勢識別器不能與UIImageView一起使用

[英]Custom Gesture Recognizer not working with UIImageView

我正在使用dysternis實現自定義的單指旋轉手勢»單指旋轉手勢識別器 ,圖像與此同時旋轉良好,但是我單擊了另一個帶有某些事件的按鈕,但是現在我必須觸摸該按鈕上的拖動觸發事件。

然后,我試圖僅將相同的手勢識別器添加到圖像視圖中,但這似乎並不好。 它無法正確旋轉圖像。 有什么需要更改的東西,或者我錯過了什么。

這是帶有我的代碼的編輯版本。 請注意,我已經啟用了與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

我已經將此自定義手勢添加到整個視圖中,但是對按鈕本身實現了另一個UITapGestureRecognizer ,現在效果很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM