UIPanGestureRecognizer를 사용하여 개체를 이동하는 방법은 무엇입니까? iPhone / iPad


80

UIPanGestureRecognizer수업 의 몇 가지 예가 있습니다 . 예를 들어 내가 읽은 와 나는 아직도 그것을 사용할 수 없습니다입니다 ...

작업중인 펜촉 파일 UIView에 해당 클래스와 함께 드래그하려는 (이미지의 흰색 사각형)이 있습니다.

여기에 이미지 설명 입력

내 .m 파일에 다음을 배치했습니다.

- (void)setTranslation:(CGPoint)translation inView:(UIView *)view
{
    NSLog(@"Test to see if this method gets executed");
}

마우스를 드래그하면 해당 메서드가 실행되지 않습니다 UIView. 나는 또한 배치를 시도했다 :

- (void)pan:(UIPanGestureRecognizer *)gesture
{
    NSLog(@"testing");
}

그리고 그 방법도 실행되지 않습니다. 내가 틀렸을지도 모르지만이 메서드는 - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event그 메서드를 배치해야하는 메서드 처럼 작동해야 하고 터치가있을 때마다 호출 될 것이라고 생각합니다.

내가 도대체 ​​뭘 잘못하고있는 겁니까? 그 방법에 연결을 그려야할까요? 그렇다면 어떻게해야합니까?

답변:


145

Working with UIGestureRecognizers 튜토리얼 을 찾았고 그것이 제가 찾고있는 것이라고 생각합니다. 다음 솔루션을 찾는 데 도움이되었습니다.

-(IBAction) someMethod {
    UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(move:)];
    [panRecognizer setMinimumNumberOfTouches:1];
    [panRecognizer setMaximumNumberOfTouches:1];
    [ViewMain addGestureRecognizer:panRecognizer];
    [panRecognizer release];
}

-(void)move:(UIPanGestureRecognizer*)sender {
    [self.view bringSubviewToFront:sender.view];
    CGPoint translatedPoint = [sender translationInView:sender.view.superview];

    if (sender.state == UIGestureRecognizerStateBegan) {
        firstX = sender.view.center.x;
        firstY = sender.view.center.y;
    }


    translatedPoint = CGPointMake(sender.view.center.x+translatedPoint.x, sender.view.center.y+translatedPoint.y);

    [sender.view setCenter:translatedPoint];
    [sender setTranslation:CGPointZero inView:sender.view];

    if (sender.state == UIGestureRecognizerStateEnded) {
        CGFloat velocityX = (0.2*[sender velocityInView:self.view].x);
        CGFloat velocityY = (0.2*[sender velocityInView:self.view].y);

        CGFloat finalX = translatedPoint.x + velocityX;
        CGFloat finalY = translatedPoint.y + velocityY;// translatedPoint.y + (.35*[(UIPanGestureRecognizer*)sender velocityInView:self.view].y);

        if (finalX < 0) {
            finalX = 0;
        } else if (finalX > self.view.frame.size.width) {
            finalX = self.view.frame.size.width;
        }

        if (finalY < 50) { // to avoid status bar
            finalY = 50;
        } else if (finalY > self.view.frame.size.height) {
            finalY = self.view.frame.size.height;
        }

        CGFloat animationDuration = (ABS(velocityX)*.0002)+.2;

        NSLog(@"the duration is: %f", animationDuration);

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:animationDuration];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
        [UIView setAnimationDelegate:self];
        [UIView setAnimationDidStopSelector:@selector(animationDidFinish)];
        [[sender view] setCenter:CGPointMake(finalX, finalY)];
        [UIView commitAnimations];
    }
}

1
놀랄 만한!! 나는 animationDuration의 계산을 좋아하고 훌륭하게 작동합니다.
最白目

39
move : (id) sender를 move : (UIPanGestureRecognizer *) sender로 변경하면 그 모든 추악한 typecasting을 수행 할 필요가 없습니다.
Wex

1
이 솔루션은 UISwitch에서 작동하지 않습니다. 또한 touchesBegan, touchesMoved 메서드를 구현하려고 시도했지만 UISwitch를 이동할 수 없습니다. 드래그만으로 UISwitch를 어떻게 움직일 수 있는지 알려 주실 수 있습니까 ??
DShah

2
제스처 인식기가 연결된보기에 대해 userInteractionEnabled = YES가 있어야합니다.
Lukas Kalinski

1
firstX와 firstY는 무엇입니까?
Krekin 2015

39
UIPanGestureRecognizer * pan1 = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(moveObject:)];
pan1.minimumNumberOfTouches = 1;
[image1 addGestureRecognizer:pan1];

-(void)moveObject:(UIPanGestureRecognizer *)pan;
{
 image1.center = [pan locationInView:image1.superview];
}

완벽한 승리!
manuelBetancurt

1
단순성에 대해 논쟁 할 수는 없지만이 솔루션에는 문제가 있습니다. 제스처를 시작하기 위해 손가락을 내리 자마자 image1잠재적으로 상당히 멀리 점프하여 그 중심이 손가락 아래에 있습니다. 보다 유동적이고 표준적인 경험을 위해의 번역 으로 조정 image1.center하는 것이 pan좋습니다.
sartak

25
-(IBAction)Method
{
      UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
      [panRecognizer setMinimumNumberOfTouches:1];
      [panRecognizer setMaximumNumberOfTouches:1];
      [ViewMain addGestureRecognizer:panRecognizer];
      [panRecognizer release];
}
- (Void)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];

    }

}

3
CGPointMake(0, 0)당신을 위해 쓸 수 있습니다 CGRectZero.
의미 - 중요한

3
@ meaning-matters 의미하지 CGPointZero않습니까?
mylogon

2
@mylogon 당신이 절대적으로 옳습니다. 감사의 마음으로 답변 해 드리겠습니다.
의미 - 중요한

1
if ([recognizer state] == UIGestureRecognizerStateChanged)    
{
    CGPoint translation1 = [recognizer translationInView:main_view];
    img12.center=CGPointMake(img12.center.x+translation1.x, img12.center.y+ translation1.y);
    [recognizer setTranslation:CGPointMake(0, 0) inView:main_view];

    recognizer.view.center=CGPointMake(recognizer.view.center.x+translation1.x, recognizer.view.center.y+ translation1.y);
}

-(void)move:(UIPanGestureRecognizer*)recognizer
{
    if ([recognizer state] == 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];
    }
}

1

@MS AppTech 답변의 신속한 2 버전

func handlePan(panGest : UIPanGestureRecognizer) {
let velocity : CGPoint = panGest.velocityInView(self.view);
        let magnitude : CGFloat = CGFloat(sqrtf((Float(velocity.x) * Float(velocity.x)) + (Float(velocity.y) * Float(velocity.y))));
        let slideMult :CGFloat = magnitude / 200;
        //NSLog(@"magnitude: %f, slideMult: %f", magnitude, slideMult);

        let slideFactor : CGFloat = 0.1 * slideMult; // Increase for more of a slide
        var finalPoint : CGPoint = CGPointMake(panGest.view!.center.x + (velocity.x * slideFactor),
                                         panGest.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(Double(slideFactor*2), delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
            panGest.view!.center = finalPoint;
            }, completion: nil)
}

0

몇 년 후 내 모자를 반지에 던졌습니다.

이미지보기의 시작 중앙을 저장해야합니다.

var panBegin: CGPoint.zero

그런 다음 변환을 사용하여 새 센터를 업데이트합니다.

if recognizer.state == .began {
     panBegin = imageView!.center

} else if recognizer.state == .ended {
    panBegin = CGPoint.zero

} else if recognizer.state == .changed {
    let translation = recognizer.translation(in: view)
    let panOffsetTransform = CGAffineTransform( translationX: translation.x, y: translation.y)

    imageView!.center = panBegin.applying(panOffsetTransform)
}

-2

Swift 2 버전 :

// start detecting pan gesture
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(TTAltimeterDetailViewController.panGestureDetected(_:)))
panGestureRecognizer.minimumNumberOfTouches = 1
self.chartOverlayView.addGestureRecognizer(panGestureRecognizer)

func panGestureDetected(panGestureRecognizer: UIPanGestureRecognizer) {
    print("pan gesture recognized")
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.