Lock direction of UIPanGestureRecognizer - ios

I have a UIPanGestureRecognizer that I use to pull up a view. the view starts at x = 160, y= 817 and when it is flicked up, I want it to go to 160,284. And When it is flicked back down I want it to automatically go back to the starting point. Here is my code so far:
-(IBAction) dragMe: (UIPanGestureRecognizer *)recognizer {
CGPoint translation = [recognizer translationInView:recognizer.view.superview];
recognizer.view.center = CGPointMake(recognizer.view.center.x, + recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:recognizer.view.superview];
if (recognizer.state == UIGestureRecognizerStateEnded) {
CGPoint velocity = [recognizer velocityInView:recognizer.view.superview];
CGFloat magnitude = sqrtf((velocity.y * velocity.y));
CGFloat slideMult = magnitude / 100;
NSLog(#"magnitude: %f, slideMult: %f", magnitude, slideMult);
float slideFactor = 0.1 * slideMult; // Increase for more of a slide
CGPoint finalPoint = CGPointMake(recognizer.view.center.x,
recognizer.view.center.y + (velocity.y * slideFactor));
finalPoint.x = MIN(MAX(finalPoint.x, 160), recognizer.view.superview.bounds.size.width);
finalPoint.y = MIN(MAX(finalPoint.y, 284), recognizer.view.superview.bounds.size.height);
[UIView animateWithDuration:slideFactor*1 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
recognizer.view.center = finalPoint;
} completion:nil];
}
}
I don't want the user to be able to move it at all horizontally, just vertically.

Related

How to animate rotated and moved UIView to its original position?

I've got an UIImageView with a pan gesture recognizer, which I move and rotate based on user action.
When user lifts the finger, I want it to be animated back to its original position, here's my code:
- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer {
if (recognizer.state == UIGestureRecognizerStateBegan) {
startX = recognizer.view.center.x;
startY = recognizer.view.center.y;
startRotation = atan2(recognizer.view.transform.b, recognizer.view.transform.a);
NSLog(#"Start Position %f %f %f", startX, startY, startRotation);
} else if (recognizer.state == UIGestureRecognizerStateEnded) {
float distance = (startX - recognizer.view.center.x) / DISTANCE_TO_ACCEPT;
CGPoint center = recognizer.view.center;
// animate back
[UIView animateWithDuration:0.5 animations:^{
NSLog(#"Position %f %f %f", recognizer.view.center.x, recognizer.view.center.y, atan2(recognizer.view.transform.b, recognizer.view.transform.a));
NSLog(#"Destination %f %f %f", startX, startY, startRotation);
NSLog(#"Translation %f %f %f", startX - center.x, startY - center.y, (startRotation - atan2(recognizer.view.transform.b, recognizer.view.transform.a)));
recognizer.view.transform = CGAffineTransformRotate(CGAffineTransformTranslate(recognizer.view.transform, startX - center.x, startY - center.y), (CGFloat) (startRotation - atan2(recognizer.view.transform.b, recognizer.view.transform.a)));
}];
} else if (recognizer.state == UIGestureRecognizerStateChanged) {
// move image
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
// rotate image
float distance = (startX - recognizer.view.center.x) / DISTANCE_TO_ACCEPT;
// cap distance
if (distance > 1) {
distance = 1;
} else if (distance < -1) {
distance = -1;
}
double rotation = 15 - startRotation;
rotation = rotation * distance;
recognizer.view.transform = CGAffineTransformRotate(recognizer.view.transform, (CGFloat) ((rotation * M_PI / 180) - atan2(recognizer.view.transform.b, recognizer.view.transform.a)));
}
}
But it never goes to the original position. It always has some kind of offset. Further movement of the image view only makes it worse.
It looks like the position is not modified during the back animation, because when I pan the image again, the start position and rotation is equal to the position and rotation it had at the end of previous movement [even though on screen the image position and rotation has changed].
What am I doing wrong here?
Thanks
Try something like this in UIGestureRecognizerStateEnded state:
recognizer.view.transform = CGAffineTransformIdentity;
recognizer.view.center = CGPointMake(startX,startY);

Pan Gesture Recognizer reset

I've added a pan gesture to my button, when i move it without any additional code, everything is well, but when i add some piece of code, which is commented in the example below, button starts reseting to its origin position.
Why is this happening? What's the reason for this?
- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer {
switch([recognizer state]){
case UIGestureRecognizerStateBegan: {
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setFrame:recognizer.view.frame];
[button setBackgroundColor: [UIColor redColor]];
// [self.view insertSubview:button belowSubview:recognizer.view];
_tempButton = button;
}break;
case UIGestureRecognizerStateChanged: {
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}break;
}
}
The code that you have added at the UIGestureRecognizerStateChanged case, move it in the header of your Action Method:
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
After that another thing for you to do is to make another Case in your Switch Method:
//This checks if you ended the pan gesture (removed finger from object)
case UIGestureRecognizerStateEnded:
{
CGPoint velocity = [recognizer velocityInView:self.view];
CGFloat magnitude = sqrtf((velocity.x * velocity.x) + (velocity.y * velocity.y));
CGFloat slideMult = magnitude / 200;
NSLog(#"magnitude: %f, slideMult: %f", magnitude, slideMult);
float slideFactor = 0.1 * slideMult; // Increase for more of a slide
CGPoint finalPoint = CGPointMake(recognizer.view.center.x + (velocity.x * slideFactor),
recognizer.view.center.y + (velocity.y * slideFactor));
finalPoint.x = MIN(MAX(finalPoint.x, 0), self.view.bounds.size.width);
finalPoint.y = MIN(MAX(finalPoint.y, 0), self.view.bounds.size.height);
[UIView animateWithDuration:slideFactor*2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
recognizer.view.center = finalPoint;
} completion:nil];
}
So what I did above in the UIGestureRecognizerStateEnded state is that, i took the final point where the user sent the image. After that, i set the center of the image equal to the point that the image was the last moment. So now the image wont return to the previous point but it will remain where the user will take it.

how to add vertical gesture in xcode 5

how do i add straight vertical slide in UIPanGestureRecognizer on image. i have some code:
- (IBAction)HandlePan:(UIPanGestureRecognizer *)panner
{
CGPoint translation = [panner translationInView:panner.view];
CGPoint newCenter = CGPointMake(self.pesawat.center.x + translation.x, self.pesawat.center.y);
int offset = 80; // pixels to offset
if (newCenter.x < offset)
newCenter = CGPointMake(offset, newCenter.y);
else if (newCenter.x > self.view.bounds.size.width - offset)
newCenter = CGPointMake(self.view.bounds.size.width - offset, newCenter.y);
self.pesawat.center = newCenter;
[panner setTranslation:CGPointMake(0, 0) inView:panner.view];
}
if i change code to like this:
CGPoint newCenter = CGPointMake(self.pesawat.center.x + translation.x, self.pesawat.center.y + translation.y);
it's become dragable(horizontal,vertical,diagonal too), what i want is just to make it's straight vertical and horizontal without image to move diagonal
and this viewdidload:
UIPanGestureRecognizer * panner = [[UIPanGestureRecognizer alloc]init];
[panner addTarget:self action:#selector(HandlePan:)];
[self.view addGestureRecognizer:panner];
could anyone give a hint?
CGPoint translation = [panner translationInView:panner.view];
if (translation.x > translation.y)
translation.y = 0.0f;
else
translation.x = 0.0f;
CGPoint newCenter = CGPointMake(self.pesawat.center.x + translation.x, self.pesawat.center.y + translation.y);
This will only apply the bigger part of translation.

How to get the coordinate of a UIView

In my app, I use PanGesture.
Now, I have a UIImageView within my main view and I can drag my UIImageView within the main view.
To which axis in the main view I have to drag my UIImageView?
Try this to move your object
or link for best tutorials http://www.raywenderlich.com/6567/uigesturerecognizer-tutorial-in-ios-5-pinches-pans-and-more
- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer {
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
if (recognizer.state == UIGestureRecognizerStateEnded) {
CGPoint velocity = [recognizer velocityInView:self.view];
CGFloat magnitude = sqrtf((velocity.x * velocity.x) + (velocity.y * velocity.y));
CGFloat slideMult = magnitude / 200;
NSLog(#"magnitude: %f, slideMult: %f", magnitude, slideMult);
float slideFactor = 0.1 * slideMult; // Increase for more of a slide
CGPoint finalPoint = CGPointMake(recognizer.view.center.x + (velocity.x * slideFactor),
recognizer.view.center.y + (velocity.y * slideFactor));
finalPoint.x = MIN(MAX(finalPoint.x, 0), self.view.bounds.size.width);
finalPoint.y = MIN(MAX(finalPoint.y, 0), self.view.bounds.size.height);
[UIView animateWithDuration:slideFactor*2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
recognizer.view.center = finalPoint;
} completion:nil];
}
}
you can use frame property of a UIView class.which gives you top,left,width and height of the view.
NSLog(#"view.frame.origin.x : %f",view.frame.origin.x);
NSLog(#"view.frame.origin.y : %f",view.frame.origin.y);
NSLog(#"view.frame.size.width : %f",view.frame.size.width);
NSLog(#"view.frame.size.height : %f",view.frame.size.height)
You can use below APIs to translate your points from one view to other and vice versa.
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;
- (IBAction)panGestureReceived:(UIPanGestureRecognizer *)gesture {
if ([gesture state] == UIGestureRecognizerStateBegan) {
myVarToStoreTheBeganPosition = [gesture locationInView:self.view];
} else if ([gesture state] == UIGestureRecognizerStateEnded) {
CGPoint myNewPositionAtTheEnd = [gesture locationInView:self.view];
// and now handle it ;)
} else if ([gesture state] == UIGestureRecognizerStateChanged) {
CGPoint myNewPositionAtTheEnd = [gesture locationInView:self.view];
// and now handle it ;)
}
}

Which label did the user last touch and how to remove it from the view

I want to know how to know which label the user last touched and how to remove that specific label from the view. I know how to change the properties for all labels, but I don't know how to find out which one was last selected.
This is how I add a label to the view.
myNewLabel.text =textField.text;
numberOfLabels++;
myNewLabel.tag=numberOfLabels;
[self.view addSubview:myNewLabel];
[shirtBackgroundView addSubview:myNewLabel];
[myNewLabel addGestureRecognizer:panGestureRecognizer];
[myNewLabel addGestureRecognizer:rotateGestureRecognizer];
[myNewLabel addGestureRecognizer:PinchGestureRecognizer];
myNewLabel.userInteractionEnabled=YES;
myNewLabel.backgroundColor=[UIColor clearColor];
[arrayForLabels addObject:myNewLabel];
Here is how I change the color of all labels.
for(int i=0;i<numberOfLabels;i++)
{
UILabel *tempLabel = [arrayForLabels objectAtIndex:i];
tempLabel.textColor=[UIColor redColor];
}
-(void)labelMoved:(UIPanGestureRecognizer *)recognizer
{
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
if (recognizer.state == UIGestureRecognizerStateEnded) {
CGPoint velocity = [recognizer velocityInView:self.view];
CGFloat magnitude = sqrtf((velocity.x * velocity.x) + (velocity.y * velocity.y));
CGFloat slideMult = magnitude / 200;
NSLog(#"magnitude: %f, slideMult: %f", magnitude, slideMult);
float slideFactor = 0.1 * slideMult; // Increase for more of a slide
CGPoint finalPoint = CGPointMake(recognizer.view.center.x + (velocity.x * slideFactor),
recognizer.view.center.y + (velocity.y * slideFactor));
finalPoint.x = MIN(MAX(finalPoint.x, 0), self.view.bounds.size.width);
finalPoint.y = MIN(MAX(finalPoint.y, 0), self.view.bounds.size.height);
[UIView animateWithDuration:slideFactor*2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
recognizer.view.center = finalPoint;
} completion:nil];
}
}
Thanks for any suggestions...
For detect UIlabels to capture taps:
label.userInteractionEnabled = YES;
UIGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapRecieved:)];
[label addGestureRecognizer:tap];
[tap release];
//repeat for each additional label
when you touched
-(void) tapRecieved:(UITapGestureRecognizer *)tap{
currentLabel = (UILabel *) tap.view;
[currentLabel removeFromSuperview];
}
You can declare a property in .h class as UILabel *lastSelectedLabel; and in your recognizer
-(void)labelMoved:(UIPanGestureRecognizer *)recognizer{
if(lastSelectedLabel!=nil){
[lastSelectedLabel removeFromSuperview];
lastSelectedLabel=recognizer.view;
}else
lastSelectedLabel=recognizer.view;
}
I think above should work..
Thanks.

Resources