转载自Creating a Custom Rotation Gesture Recognizer for iOS Apps
创建自定义的旋转手势
主要重写了4个方法:
- (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
主要代码如下,原理见注释:
@protocol CAYSwirlGestureRecognizerDelegate <UIGestureRecognizerDelegate>
@end
@interface CAYSwirlGestureRecognizer : UIGestureRecognizer
@property CGFloat currentAngle;
@property CGFloat previousAngle;
@end
#import "CAYSwirlGestureRecognizer.h"
@interface CAYSwirlGestureRecognizer ()
@property (strong, nonatomic) id target;
@property (nonatomic) SEL action;
@end
@implementation CAYSwirlGestureRecognizer
- (id)initWithTarget:(id)target action:(SEL)action {
if (self = [super initWithTarget:target action:action]) {
self.target = target;
self.action = action;
}
return self;
}
- (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];
UITouch *touch = [touches anyObject];
self.currentAngle = [self getTouchAngle:[touch locationInView:touch.view]];
self.previousAngle = [self getTouchAngle:[touch previousLocationInView:touch.view]];
if ([self.target respondsToSelector:self.action]) {
[self.target performSelector:self.action withObject:self];
}
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
[super setState:UIGestureRecognizerStateEnded];
}
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent *)event {
[super touchesCancelled:touches withEvent:event];
[super setState:UIGestureRecognizerStateCancelled];
}
- (float)getTouchAngle:(CGPoint)touch {
// Translate into cartesian space with origin at the center of a 320-pixel square
/*
*1.这里的view的width是320宽的
*2.相当于把view的原点从左上角,移动到中心点,并且把Y转的方向翻转,向上为正,并且0°位于Y轴
*/
float x = touch.x - 160;
float y = -(touch.y - 160);
// Take care not to divide by zero!
if (y == 0) {
if (x > 0) {
return M_PI_2;
}
else {
return 3 * M_PI_2;
}
}
float arctan = atanf(x/y);
// Figure out which quadrant we're in
// Quadrant I 第一象限
if ((x >= 0) && (y > 0)) {
return arctan;
}
// Quadrant II 第二象限
else if ((x < 0) && (y > 0)) {
return arctan + 2 * M_PI;
}
// Quadrant III
else if ((x <= 0) && (y < 0)) {
return arctan + M_PI;
}
// Quadrant IV
else if ((x > 0) && (y < 0)) {
return arctan + M_PI;
}
return -1;
}
@end
在View上添加手势:
self.swirlGestureRecognizer = [[CAYSwirlGestureRecognizer alloc] initWithTarget:self action:@selector(rotationAction:)];
[self.swirlGestureRecognizer setDelegate:self];
[self.controlsView addGestureRecognizer:self.swirlGestureRecognizer];
action方法主要是做变换旋转:
- (void)rotationAction:(id)sender {
if([(CAYSwirlGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
return;
}
CGFloat direction = ((CAYSwirlGestureRecognizer*)sender).currentAngle - ((CAYSwirlGestureRecognizer*)sender).previousAngle;
bearing += 180 * direction / M_PI;
if (bearing < -0.5) {
bearing += 360;
}
else if (bearing > 359.5) {
bearing -= 360;
}
CGAffineTransform knobTransform = self.knob.transform;
CGAffineTransform newKnobTransform = CGAffineTransformRotate(knobTransform, direction);
[self.knob setTransform:newKnobTransform];
self.position.text = [NSString stringWithFormat:@"%dº", (int)lroundf(bearing)];
}
最终的效果如下: