iphone development - UIRotationGestureRecognizer (Clockwise & counter Clockwise detection)? - iphone

Is there a way to detect if the rotation done by the user is in clockwise or counter clockwise direct???
I searched for that but couldn't find an answer !
My code looks like this:
UIGestureRecognizer *recognizer;
recognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(spin)];
[self.rotating addGestureRecognizer:recognizer];
[recognizer release];

the rotation property will tell you the rotation in radians. A negative value would indicate the rotation is clockwise, and a positive value indicates counter-clockwise.
Example:
UIGestureRecognizer *recognizer;
recognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(spin:)]; // <-- Note the colon after the method name
[self.rotating addGestureRecognizer:recognizer];
[recognizer release];
- (void)spin:(UIGestureRecognizer *)gestureRecognizer {
CGFloat rotation = gestureRecognizer.rotation;
if (rotation < 0) {
// clockwise
} else {
// counter-clockwise
}
}

Swift version - imagine you've connected your UIRotationGestureRecognizer to an IBAction and are passing in the UIRotationGestureRecognizer as argument recognizer. You could very easily test direction with the following:
if recognizer.rotation < 0 {
print("Negative rotation value means anticlockwise rotation detected")
} else if recognizer.rotation > 0 {
print("Positive rotation value means clockwise rotation detected")
}

Related

objective C enable UIScrollView scroll while UIGestureRecognizerStateChanged

I added a -(void) detectTouch: (UIPanGestureRecognizer *) event for UIScrollView and detecting the angle on which user is moving his finger. My task is to scroll the UIScrollView horizontally only when user is moving the finger between 0 - 30 degrees (just to make sure he is drawing a horizontal straight line) otherwise I have to disable the UIScrollView scroll.
I am detecting the angle by drawing a triangle using the touch starting point and ending point.
Problem: I enabled the UIScrollView scroll when the angle is < 30 degrees but this is not working on the first time. Although I enabled scroll using scrollEnabled = YES it is working only when user is stopped touching the screen (taking the finger from the screen).
The following code I used to
- (void)viewDidLoad
{
[super viewDidLoad];
[self PanGesture:self.view callBack:#selector(detectTouch:) delegate:self];
incrementer = 0;
}
-(void) detectTouch: (UIPanGestureRecognizer *) event{
// Calculating point A on gesture starts
if(event.state == UIGestureRecognizerStateBegan){
pointA.x = fabs([event translationInView:event.view].x);
pointA.y = fabs([event translationInView:event.view].y);
NSLog(#"A: %f, %f", pointA.x, pointA.y);
}
incrementer += 1;
// Start calculating Point B, Point C on calling this function 3 times
if(incrementer >= 3){
// Calculating point C
pointC.x = fabs([event translationInView:event.view].x);
pointC.y = fabs([event translationInView:event.view].y);
NSLog(#"C: %f, %f", pointC.x, pointC.y);
// calculate pointB using A, C
pointB.x = fabs(pointC.x);
pointB.y = fabs(pointA.y);
NSLog(#"B: %f, %f", pointB.x, pointB.y);
float X = pointB.x - pointA.x;
float Y = pointC.y - pointB.y;
float angle = (atan(fabs(Y) / fabs(X)) * 180 / M_PI);
if(angle > 30){
// This disable is not working on while user is moving the finger
self.myScrollView.scrollEnabled = NO;
NSLog(#"UIScroll Disabled");
}else{
// This enable is not working on while user is moving the finger
self.myScrollView.scrollEnabled = YES;
NSLog(#"UIScroll Enabled");
}
incrementer = 0;
}
}
How can I enable UIScrollView scroll while user is moving the touch?
Since UIScrollView seems to accept scrolling only with a new touch after you set .scrollEnabled to YES, I would do the following:
set .scrollEnabled to NO
Track the touch (e. g. with touchesMoved::)
check whether you 30 degrees condition is met
use the movement to adjust UIScrollView.contentOffset

Preventing a rotated CGAffineTransform from being wrecked by view autorotation

I have a subclass of a UIImageView containing some gesture recognisers that I'm using to apply transforms to itself. I'm having no issues with panning or scaling, but the rotated transform is causing problems when the device itself is rotated. Basically each time the device is rotated it will have the effect of scaling the image...
I guess it makes sense that the rotation of everything might cause problems with a rotated transform but does anyone know any ways around this kind of behaviour? Preferably something that can be implemented within the UIImageView subclass? I need other sibling views to autoresize so I can't disable "autoresize subviews" in the parent view.
Here's the code responsible for creating the rotated transform if it helps:
- (void)setUpRotation
{
UIRotationGestureRecognizer *newRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(handleRotationGesture)];
newRecognizer.delegate = self;
self.rotationRecognizer = newRecognizer;
[self addGestureRecognizer:self.rotationRecognizer];
[newRecognizer release];
self.userInteractionEnabled = YES;
}
- (void)handleRotationGesture
{
// Initial state
if(self.rotationRecognizer.state == UIGestureRecognizerStateEnded)
{
lastRotation = 0.0;
return;
}
CGFloat rotation = 0.0 - (lastRotation - self.rotationRecognizer.rotation);
CGAffineTransform currentTransform = self.transform;
self.transform = CGAffineTransformRotate(currentTransform,rotation);
lastRotation = self.rotationRecognizer.rotation;
}
This is on iOS 5.0 btw.

iPhone4 iOS5 UIRotationGestureRecognizer, how to remember rotation offset for subsequent rotations?

I'm trying to create a knob-like behavior in one of my views with a UIRotationGestureRecognizer. This works, and positions the view as expected. However, every single time a gesture is performed, the rotation of the recognizer resets, so the knob starts at 0 every time.
How can I remember the last rotation of the UIRotationGestureRecognizer to let the user adjust the knob UIView without resetting it every single time?
I'm trying to make the recognizer start calculating rotation changes from the view's last known rotation:
knob starts at 0, recognizer is at 0
recognizer is rotated to 45 degrees
recognizer stops rotating
the knob is left at 45 degrees //this is already happening with the provided code snippet
next touch:
//this is what's is happening
recognizer starts at 0, rotates the knob back to 0
//I want it to be:
recognizer starts at 45, rotates the knob as in the example above.
- (IBAction)rotateView:(id)sender {
if([sender isKindOfClass:[UIRotationGestureRecognizer class]])
{
UIRotationGestureRecognizer* recognizer = sender;
CGAffineTransform transform = CGAffineTransformMakeRotation([recognizer rotation]);
rotatingView.transform = transform;
}
}
You should be able to get the current rotation of the rotatingView from it's transform property. Store this value into a savedRotation variable when the gesture begins. Make sure to assign a delegate to handle the gestureRecognizerShouldBegin callback.
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)recognizer
{
savedRotation = atan2(rotatingView.transform.b, rotatingView.transform.a);
return YES;
}
- (void)rotateView:(UIRotationGestureRecognizer*)recognizer
{
rotatingView.transform = CGAffineTransformMakeRotation(recognizer.rotation+savedRotation);
}
Transform the transform:
rotatingView.transform = CGAffineTransformRotate(rotatingView.transform, [recognizer rotation]);
You have to make sure that you reset the rotation after the transform. Otherwise they will stack on top of each other and you get the "interesting" behavior.
rotatingView.transform = CGAffineTransformScale(rotatingView.transform, recognizer.scale, recognizer.scale);
[recognizer setRotation:0]; // this line
You should also do this for any translation or scaling transformations that you may do when handling gestures. The methods there are:
[recognizer setScale:1];
[recognizer setTranslation:CGPointZero inView:recognizer.view.superview];

Long press drops 2 pins with each tap

I got my app dropping pin by long tap, i allow users to drop only two pins and its working i guess.. but every time i tap to add a pin in the simulator it adds two pins (not only one).. here is the code:
-(void) handleLongPressGesture:(UIGestureRecognizer*)sender
{
if (pinId < 3) {
// Here we get the CGPoint for the touch and convert it to
// latitude and longitude coordinates to display on the map
CGPoint point = [sender locationInView:self.mapView];
CLLocationCoordinate2D coord = [self.mapView convertPoint:point
toCoordinateFromView:self.mapView];
if (pinId == 1) {
lat1 = coord.latitude;
long1 = coord.longitude;
MapAppAnnotation* annotation;
annotation = [[MapAppAnnotation alloc] initWithCoordinate:coord
andID:pinId];
[mapView addAnnotation:annotation];
MKCircle* circle = [MKCircle circleWithCenterCoordinate:coord
radius:5000];
[mapView addOverlay:circle];
pinId++;
} else {
lat2 = coord.latitude;
long2 = coord.longitude;
MapAppAnnotation* annotation2;
annotation2 = [[MapAppAnnotation alloc] initWithCoordinate:coord
andID:pinId];
[mapView addAnnotation:annotation2];
}
}
}
I would like to know if is my fault (code error..) or is the iPhone simulator that get my long-mouse-pressure like two different long pressures.. is this possible?
Your selector is being called once when the gesture begins, and again when it ends. Check the gesture's state and act on the relevant one.
-(void)handleLongPressGesture:(UIGestureRecognizer*)sender
{
if (sender.state != UIGestureRecognizerStateEnded) return;
// otherwise, handle the gesture as before
}
The class reference for UILongPressGestureRecognizer says:
Long-press gestures are continuous.
The gesture begins
(UIGestureRecognizerStateBegan) when
the number of allowable fingers
(numberOfTouchesRequired) have been
pressed for the specified period
(minimumPressDuration) and the touches
do not move beyond the allowable range
of movement (allowableMovement). The
gesture recognizer transitions to the
Change state whenever a finger moves,
and it ends
(UIGestureRecognizerStateEnded) when
any of the fingers are lifted.

swipeGesture, touchMoved are called sametime?

i want to do different operation in SwipeGesture and TouchMoved.But both are called
when we swipe.any help please?
Drecoginizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(handleSwipeFromD:)];
Drecoginizer.direction = UISwipeGestureRecognizerDirectionDown;
[self.view addGestureRecognizer:Drecoginizer];
As I understood you do not want the selector to react on swipe gesture if this swipe is outside of the circle. In this case, in the beginning of the swipe selector you should check if the swipe is over the circle something like so:
CGPoint lClick = [recognizer locationOfTouch:0 inView:self.view];
//Distance from the center of the circle to the taped point
int lDistance = sqrt(pow(lClick.x - lCircleCenter.x, 2) + pow(lClick.y - lCircleCenter.y, 2));
if ((int)lDistance > (int)lCircleRadius) {
return;
}
Hope it helps you