我正在實現一個使用dysternis » An one finger rotation gesture recognizer的自定義單指旋轉手勢,並且圖像旋轉得很好,但我有另一個按鈕,點擊它時有一些事件,但現在我必須觸摸拖動該按鈕來觸發事件。自定義手勢識別器不與UIImageView一起工作
我曾嘗試將相同的手勢識別器添加到圖像視圖中,但效果並不理想。它沒有正確旋轉圖像。有沒有需要改變的東西,或者我錯過了一些東西。
這裏是我的代碼的編輯版本。請注意,我已啓用用戶與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
顯示您的代碼以獲得幫助。 – 2012-04-18 16:01:45