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 ;)
}
}
Related
I'm trying to track the horizontal distance that a user has swiped using a UIPanGestureRecognizer, but I'm having difficulty interpreting the results. Here is the code that I am using:
- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer {
CGPoint startLocation;
if (recognizer.state == UIGestureRecognizerStateBegan) {
startLocation = [recognizer locationInView:self.view];
}
if (recognizer.state == UIGestureRecognizerStateEnded) {
CGPoint stopLocation = [recognizer locationInView:self.view];
CGFloat dx = stopLocation.x - startLocation.x;
NSLog(#"dx: %f", dx);
}
}
If I swipe left-to-right, I get output something like this:
dx: 50328911327402404790403072.000000
My screen is only 320 pixels wide, so my end result cannot be greater than 320. Is there a problem with my code or am I just interpreting this number incorrectly? How can I get this value stated in pixels? Thanks!
startLocation doesn't persist after handlePan: returns, so you're getting garbage.
Either declare startLocation as static or save it in an instance variable / property.
You can use UIPanGestureRecognizer as below:-
CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view];
if ([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {
firstX = [[sender view] center].x;
firstY = [[sender view] center].y;
}
translatedPoint = CGPointMake(firstX+translatedPoint.x, firstY);
[[sender view] setCenter:translatedPoint];
if ([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
CGFloat velocityX = (0.2*[(UIPanGestureRecognizer*)sender velocityInView:self.view].x);
CGFloat finalX = translatedPoint.x + velocityX;
CGFloat finalY = firstY;
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.
I'm trying to use UIPanGestureRecognizer to flip an UIView. I'm using below code to handle flipping the view,
- (void)handlePan:(UIPanGestureRecognizer*)gesture{
CGPoint translation = [gesture translationInView:self.view];
NSLog(#"PAN X VALUE %f", translation.x );
double percentageOfWidth = translation.x / (gesture.view.frame.size.width / 2);
float angle = (percentageOfWidth * 100) * M_PI_2 / 180.0f;
CALayer *layer = testView.layer;
CATransform3D flipTransform = CATransform3DIdentity;
flipTransform.m34 = -0.002f;
flipTransform = CATransform3DRotate(flipTransform, angle, 0.0f, 1.0f, 0.0f);
layer.transform = flipTransform;
}
My problem is when i pan, sometimes there are some quick jumpings happen, I believe thats because translation.x(PAN X VALUE) value jumps from few points ahead, In my case i need it to be very smooth.
Any help greatly appreciated.
Thanks in advance.
You can use the gestureRecognizerShouldBegin method, which u can limit the UIPanGestureRecognizer sensitivity.
Example:
- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)panGestureRecognizer {
CGPoint translation = [panGestureRecognizer translationInView:self.view];
return fabs(translation.y) < fabs(translation.x);
}
Here's how I solved this for a cube rotation - just take the amount dragged and divide:
- (void)panHandle:(UIPanGestureRecognizer*)recognizer;
{
if ([recognizer state] == UIGestureRecognizerStateBegan)
{
CGPoint translation = [recognizer translationInView:[self superview]];
_startingX = translation.x;
}
else if ([recognizer state] == UIGestureRecognizerStateChanged)
{
CGPoint translation = [recognizer translationInView:[self superview]];
CGFloat angle = -(_startingX - translation.x) / 4;
//Now do translation with angle
_transitionContainer.layer.sublayerTransform = [self->_currentMetrics asTransformWithAngle:angle];
}
else if ([recognizer state] == UIGestureRecognizerStateEnded)
{
[self transitionOrReturnToOrigin];
}
}
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.
I have a UIView I am trying to move up and down the screen, however I only wish to enable it to pan so that you cannot drag the view down when it is in its normal position (0, 0)
I tried to detect when the recognizer's center is not half the height of the view, however the view is then immovable, and the center is always half the height (230 in this case).
Any ideas?
- (IBAction)panDetected:(UIPanGestureRecognizer *)recognizer {
CGPoint translation = [recognizer translationInView:self.view];
NSLog(#"\ncenter.y: %f\ntranslation.y: %f\n", recognizer.view.center.y, translation.y);
if (recognizer.view.center.y > ([[UIScreen mainScreen] bounds].size.height - 20)/2) {
return;
}
recognizer.view.center = CGPointMake(recognizer.view.center.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}
Instead of manually computing whether the points are within the view's bounds, use CGRectContainsPoint(rect, point). This is what works for me, and I like it because it's shorter and more readable:
func handlePan(pan: UIPanGestureRecognizer) {
switch pan.state {
case .Began:
if CGRectContainsPoint(self.pannableView.frame, pan.locationInView(self.pannableView)) {
// Gesture started inside the pannable view. Do your thing.
}
}
CGPoint translation = [recognizer translationInView:self.view];
CGPoint finalpoint = CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y+ translation.y);
//limit the boundary
if ((recognizer.view.frame.origin.x>0 && translation.x > 0) || (recognizer.view.frame.origin.x + recognizer.view.frame.size.width<=320 && translation.x < 0))
finalpoint.x = recognizer.view.center.x;
if ((recognizer.view.frame.origin.y>0 && translation.y > 0) || (recognizer.view.frame.origin.y + recognizer.view.frame.size.height<=self.view.frame.size.height && translation.y < 0))
finalpoint.y = recognizer.view.center.y;
//set final position
recognizer.view.center = finalpoint;
[recognizer setTranslation:CGPointZero inView:self.view];
try
CGPoint translation = [recognizer translationInView:self.view];
if (translation.x+recognizer.view.frame.origin.x<0||translation.y+recognizer.view.frame.origin.y<0)
{
return;
}
recognizer.view.center = CGPointMake(recognizer.view.center.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x, MAX(recognizer.view.center.y + translation.y, ([[UIScreen mainScreen] bounds].size.height - 20)/2));