adit
adit

Reputation: 33644

what is wrong with this pan gesture recognizer action?

I am unsure why this doesn't pan when I move the view?

CGPoint translation = [recognizer translationInView:self.view];


    if ((recognizer.view.frameY + translation.y >= self.view.frameHeight - recognizer.view.frameHeight)) {
        CGPoint newOrigin = CGPointMake(self.view.bounds.size.width, roundf(recognizer.view.frameY + translation.y));
        recognizer.view.frameOrigin = newOrigin;
        NSLog(@"FRAME ORIGIN %@", NSStringFromCGPoint(recognizer.view.frameOrigin));
    } 

Upvotes: 3

Views: 2893

Answers (3)

Rob
Rob

Reputation: 437492

I was unclear as to some of your custom variables and the like, so rather than debugging your code, I thought I'd show you how I'd do the dragging of a view using a UIPanGestureRecognizer.

Thus, assuming (a) the gesture has been added to the view being dragged; and (b) that view is contained within a superview that you want to constrain the movement of the view, the code might look like:

- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
    static CGRect originalFrame;

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        originalFrame = gesture.view.frame;
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        CGPoint translate = [gesture translationInView:gesture.view.superview];
        CGRect newFrame = CGRectMake(originalFrame.origin.x + translate.x,
                                     originalFrame.origin.y + translate.y,
                                     originalFrame.size.width,
                                     originalFrame.size.height);

        if (CGRectContainsRect(gesture.view.superview.bounds, newFrame))
            gesture.view.frame = newFrame;
    }
}

While the above enjoys a certain simplicity, I think we can improve upon the user experience. Notably, the above code will not do anything if the user drags the view outside of it's superview (e.g. drag past the left border and it freezes there, even as you move your finger up and down; not very elegant). I think that the following is a more graceful user interface (but a tiny bit more complicated to read the code), where as the user drags their finger, we'll drag the object to the closest point in the superview that corresponds to where the user's finger is.

- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
    static CGRect originalFrame;

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        originalFrame = gesture.view.frame;
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        CGPoint translate = [gesture translationInView:gesture.view.superview];
        CGRect newFrame = CGRectMake(fmin(gesture.view.superview.frame.size.width - originalFrame.size.width, fmax(originalFrame.origin.x + translate.x, 0.0)),
                                     fmin(gesture.view.superview.frame.size.height - originalFrame.size.height, fmax(originalFrame.origin.y + translate.y, 0.0)),
                                     originalFrame.size.width,
                                     originalFrame.size.height);

        gesture.view.frame = newFrame;
    }
}

Upvotes: 6

thavasidurai
thavasidurai

Reputation: 2002

Did pan gesture method called? if not set user interaction enabled. you can use below code.

- (void)handlePan:(UIPanGestureRecognizer *)recognizer {


CGPoint translation = [recognizer translationInView:recognizer.view.superview];

recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.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.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), recognizer.view.superview.bounds.size.width);
    finalPoint.y = MIN(MAX(finalPoint.y, 0), recognizer.view.superview.bounds.size.height);

    [UIView animateWithDuration:slideFactor*2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
        recognizer.view.center = finalPoint;
    } completion:nil];

} 



}

Upvotes: 1

Levi
Levi

Reputation: 7343

In the if you should write <= instead of >=, since the origin is in the upper left corner

Upvotes: 0

Related Questions