Перемещение UIView в родительском UIView (UIPanGestureRecognizer)

Я использую следующий код для перемещения UIImageView, который присутствует внутри UIView.

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

}

Я хотел бы сделать так, чтобы UIView не перемещался за пределы родительского представления. В тот же момент изображение может перемещаться по всему экрану.

Ответ 1

Сначала получите новый фрейм вашего UIImageView и проверьте, полностью ли он внутри супервизора, используя метод CGRectContainsRect(). Если да, установите рамку UImageView's в новый кадр.

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

    CGPoint translation = [recognizer translationInView:self.view];
    CGRect recognizerFrame = recognizer.view.frame;
    recognizerFrame.origin.x += translation.x;
    recognizerFrame.origin.y += translation.y; 

    // Check if UIImageView is completely inside its superView
    if (CGRectContainsRect(self.view.bounds, recognizerFrame)) {
        recognizer.view.frame = recognizerFrame;
    }
    // Else check if UIImageView is vertically and/or horizontally outside of its
    // superView. If yes, then set UImageView frame accordingly.
    // This is required so that when user pans rapidly then it provides smooth translation.
    else {
        // Check vertically
        if (recognizerFrame.origin.y < self.view.bounds.origin.y) {
            recognizerFrame.origin.y = 0;
        }        
        else if (recognizerFrame.origin.y + recognizerFrame.size.height > self.view.bounds.size.height) {
            recognizerFrame.origin.y = self.view.bounds.size.height - recognizerFrame.size.height;
        }

        // Check horizantally
        if (recognizerFrame.origin.x < self.view.bounds.origin.x) {
            recognizerFrame.origin.x = 0;
        }
        else if (recognizerFrame.origin.x + recognizerFrame.size.width > self.view.bounds.size.width) {
            recognizerFrame.origin.x = self.view.bounds.size.width - recognizerFrame.size.width;
        }
    }

    // Reset translation so that on next pan recognition
    // we get correct translation value
    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}

Убедитесь, что вы передали bounds superView и frame из UIImageView, чтобы обе CGRects находились в одной и той же системе координат.

Ответ 2

Попробуйте:

- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer 
{
    if (gesture.state==UIGestureRecognizerStateChanged || gesture.state == UIGestureRecognizerStateEnded){
        UIView *superview = recognizer.view.superview;
        CGSize superviewSize = superview.bounds.size;
        CGSize thisSize = recognizer.view.size;
        CGPoint translation = [recognizer translationInView:self.view];
        CGPoint center = CGPointMake(recognizer.view.center.x + translation.x,
                                 recognizer.view.center.y + translation.y);

        CGPoint resetTranslation = CGPointMake(translation.x, translation.y);

        if(center.x - thisSize.width/2 < 0)
            center.x = thisSize.width/2;
        else if (center.x + thisSize.width/2 > superviewSize.width)
            center.x = superviewSize.width-thisSize.width/2;
        else
            resetTranslation.x = 0; //Only reset the horizontal translation if the view *did* translate horizontally

        if(center.y - thisSize.height/2 < 0)
            center.y = thisSize.height/2;
        else if(center.y + thisSize.height/2 > superviewSize.height)
            center.y = superviewSize.height-thisSize.height/2;
        else
            resetTranslation.y = 0; //Only reset the vertical translation if the view *did* translate vertically

        recognizer.view.center = center;
        [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
    }
}

Таким образом, он никогда не будет перемещаться за пределы родительского представления, и он просто "прилипнет" к краю, если вы попытаетесь вывести его из пределов!

Ответ 3

Вам нужно установить значение recognizer.view.center в новое значение, только если его frame находится внутри bounds его родительского представления. Используйте CGRectContainsRect на recognizer.view.superview.bounds и recognizer.view.frame, чтобы убедиться, что они содержатся.

Если вы хотите, чтобы представление изображения перемещалось за пределы его родительского представления, пока центральная точка представления не находится за пределами родительских границ, вы можете использовать метод convertPoint:toView UIView и убедиться, что новый CGPoint не находится за пределами ваших родительских границ.

Ответ 4

if (gesture.state==UIGestureRecognizerStateChanged){

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

CGRect rectToCheck=CGRectMake(yourView.frame.origin.x+translation.x,       yourView.frame.origin.y+translation.y, CGRectGetWidth(yourView.frame),     CGRectGetHeight(yourView.frame));

     if(CGRectContainsRect(self.view.bounds,rectToCheck))// check that the rect that is   going to form lies within the bounds of self.view
     {

     yourView.frame=CGRectMake(yourView.frame.origin.x+translation.x,  yourView.frame.origin.y+translation.y, CGRectGetWidth(yourView.frame),  CGRectGetHeight(yourView.frame)); 
     }
     [gesture setTranslation:CGPointZero yourView]; // important to set this 

 }

P.S. Используйте блок состояния жестов для запуска, панорамирования, удаления. то есть UIGestureRecognizerStateBegan UIGestureRecognizerStateChanged UIGestureRecognizerStateEnded