iOS: Wrong effect with “recognizer.view.center = C

2019-08-11 15:15发布

I am using the locationInView to set the position of my bouton when the user release it. After release, I give the location stored before but in fact, my button is not going back to the correct position.

This my code:

- (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];

    static CGPoint startLocation;

    if (recognizer.state == UIGestureRecognizerStateBegan) {
        startLocation = [recognizer locationInView:self.view];
        NSLog(@"Began: %d" @"-" @"%d", (int)startLocation.x , (int)startLocation.y);
    }

    if (recognizer.state == UIGestureRecognizerStateEnded)
    {
        NSLog(@"Ended Bef: %d" @"-" @"%d", (int)startLocation.x, (int)startLocation.y);
        recognizer.view.center =  CGPointMake(startLocation.x, startLocation.y);

        startLocation = [recognizer locationInView:self.view];
        NSLog(@"Ended Aft: %d" @"-" @"%d", (int)startLocation.x, (int)startLocation.y);

    }

 }

In fact, the instruction:

recognizer.view.center =  CGPointMake(startLocation.x, startLocation.y);

give a wrong effect. Someone know why?

2条回答
看我几分像从前
2楼-- · 2019-08-11 15:51

A couple of thoughts:

  1. I'd suggest making sure you capture startLocation before you do any changing of the center.

  2. You're using the location of the user's touch for startLocation. You really should initialize this with the center of the recognizer.view. It's exceedingly unlikely that the user started their gesture precisely in the center of the button. And as a result, you're unlikely to return back at the original location.

Somewhat unrelated, but:

  1. You don't need to use CGMakePoint when resetting the center of recognizer.view in the UIGestureRecognizerStateEnded clause. You can use CGPointMake if you really want, but it's unnecessary. You can just use startLocation, if you want.

  2. You might want to animate the returning of the view back to that startLocation. It's jarring to have it immediately go there.

  3. As an aside, if you've saved startLocation, you don't need to continually reset the translation. Just use startLocation plus translation. Seems more clear to me, but clearly that's subjective.

  4. I personally think NSStringFromCGPoint is very useful when logging CGPoint structures.

So, I'd suggest:

- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer
{
    static CGPoint startLocation;

    if (recognizer.state == UIGestureRecognizerStateBegan)
    {
        startLocation = recognizer.view.center;
        NSLog(@"Began: %@", NSStringFromCGPoint(startLocation));
    }

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

    recognizer.view.center = CGPointMake(startLocation.x + translation.x,
                                         startLocation.y + translation.y);

    if (recognizer.state == UIGestureRecognizerStateEnded)
    {
        NSLog(@"Ended Bef: %@", NSStringFromCGPoint(startLocation));

        [UIView animateWithDuration:0.25
                         animations:^{
                             recognizer.view.center = startLocation;
                         }];

        CGPoint finalLocation = [recognizer locationInView:self.view];
        NSLog(@"Ended Aft: %@", NSStringFromCGPoint(finalLocation));
    }
}
查看更多
\"骚年 ilove
3楼-- · 2019-08-11 16:03

I think you should try using

startLocation = [recognizer locationOfTouch:0 inView:self.view];

instead of

startLocation = [recognizer locationInView:self.view];
查看更多
登录 后发表回答