Як використовувати UIPanGestureRecognizer для переміщення об’єкта? iPhone / iPad


80

Є кілька прикладів UIPanGestureRecognizerзанять. Наприклад, я прочитав це і досі не можу користуватися ним ...

У файлі nib, над яким я працюю, у мене є 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

Я знайшов підручник Робота з 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
Дивовижний!! Мені подобається розрахунок тривалості анімації, чудово працює.
最 白 目

39
Якщо ви зміните відправника переміщення: (ідентифікатор) на пересилання: (UIPanGestureRecognizer *) відправника, вам не доведеться виконувати все те потворне випуску тексту.
Wex

1
Це рішення не працює для UISwitch. Також я спробував реалізувати методи touchesBegan, touchesMoved, але не зміг перемістити UISwitch. Підкажіть, будь ласка, як я можу перемістити UISwitch просто перетягуванням ??
DShah

2
Не забудьте мати userInteractionEnabled = ТАК для подання, з яким пов'язаний розпізнавач жестів.
Лукас Калінський

1
Що таке firstX і firstY?
Крекін

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перекладу для більш плавного та стандартного досвіду.
сартак 03.03.18

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
@ значення-питання Ви не маєте на увазі 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

швидка 2 версія відповіді @MS AppTech

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")
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.