8
votes

L'uipinchgesure peut-il être fusionné et uipangesturerecognizer?

Je me lance un peu tente de déterminer s'il est possible de créer un seul reconnaissance combinée de geste combinant uipinchgesurerecognizer à Uipangesurerecognizer.

J'utilise PAN pour View Traduction et Pinch pour la vue de l'échelle. Je fais une concaténation de matrice incrémentielle pour dériver une matrice de transformation finale résultante appliquée à la vue. Cette matrice a à la fois une échelle et une traduction. En utilisant des reconnaissants de gestes séparés conduit à un mouvement / à la mise à l'échelle gênante. Pas ce que je veux. Ainsi, je veux gérer la concaténation de l'échelle et la traduction une fois dans un seul geste. Quelqu'un peut-il perdre une lumière sur la façon de faire cela?


1 commentaires

Doug, j'ai mis à jour ma réponse avec le code source complet et un exemple de projet.


3 Réponses :


20
votes

6/14/14: code d'échantillon mis à jour pour iOS 7+ avec arc. strong>

Les uigesturalisateurs peuvent travailler ensemble et il vous suffit de vous assurer de ne pas corbeler la transformation de la vue actuelle matrice. Utilisez la méthode CGAFFINETRANSFALEFALE et les méthodes associées qui prennent une transformation en tant qu'entrée, plutôt que de la créer à partir de zéro (sauf si vous maintenez la rotation actuelle, la balance ou la translation vous-même. P>

Télécharger Xcode Project H2>
  • Exemple de projet UIPInchgesture sur Github . Li> ul>

    Remarque: iOS 7 se comporte bizarre avec UIView de UIView in IB qui ont une casserole / pincée / pivoter des gestes appliqués. IOS 8 la corrige, mais ma solution de contournement est d'ajouter toutes les vues dans le code comme cet exemple de code. P>

    Vidéo de démonstration h2>

     démonstration uipinchgesture vidéo p>

    1. ajoutez-les à une vue et conforme au protocole UIGESTurerCOnderDelegate P>

      - (void)handlePanGesture:(UIPanGestureRecognizer *)panGesture {
          CGPoint translation = [panGesture translationInView:panGesture.view.superview];
      
          if (UIGestureRecognizerStateBegan == panGesture.state ||UIGestureRecognizerStateChanged == panGesture.state) {
              panGesture.view.center = CGPointMake(panGesture.view.center.x + translation.x,
                                                   panGesture.view.center.y + translation.y);
              // Reset translation, so we can get translation delta's (i.e. change in translation)
              [panGesture setTranslation:CGPointZero inView:self.view];
          }
          // Don't need any logic for ended/failed/canceled states
      }
      
      - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinchGesture {
      
          if (UIGestureRecognizerStateBegan == pinchGesture.state ||
              UIGestureRecognizerStateChanged == pinchGesture.state) {
      
              // Use the x or y scale, they should be the same for typical zooming (non-skewing)
              float currentScale = [[pinchGesture.view.layer valueForKeyPath:@"transform.scale.x"] floatValue];
      
              // Variables to adjust the max/min values of zoom
              float minScale = 1.0;
              float maxScale = 2.0;
              float zoomSpeed = .5;
      
              float deltaScale = pinchGesture.scale;
      
              // You need to translate the zoom to 0 (origin) so that you
              // can multiply a speed factor and then translate back to "zoomSpace" around 1
              deltaScale = ((deltaScale - 1) * zoomSpeed) + 1;
      
              // Limit to min/max size (i.e maxScale = 2, current scale = 2, 2/2 = 1.0)
              //  A deltaScale is ~0.99 for decreasing or ~1.01 for increasing
              //  A deltaScale of 1.0 will maintain the zoom size
              deltaScale = MIN(deltaScale, maxScale / currentScale);
              deltaScale = MAX(deltaScale, minScale / currentScale);
      
              CGAffineTransform zoomTransform = CGAffineTransformScale(pinchGesture.view.transform, deltaScale, deltaScale);
              pinchGesture.view.transform = zoomTransform;
      
              // Reset to 1 for scale delta's
              //  Note: not 0, or we won't see a size: 0 * width = 0
              pinchGesture.scale = 1;
          }
      }
      
      - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
          return YES; // Works for most use cases of pinch + zoom + pan
      }
      
    2. Mettez en œuvre des méthodes de geste p>

      @interface ViewController () <UIGestureRecognizerDelegate>
      
      @end
      
      @implementation ViewController
      
      - (void)viewDidLoad
      {
          [super viewDidLoad];
      
          UIView *blueView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 150, 150)];
          blueView.backgroundColor = [UIColor blueColor];
          [self.view addSubview:blueView];
          [self addMovementGesturesToView:blueView];
      
          // UIImageView's and UILabel's don't have userInteractionEnabled by default!
          UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"BombDodge.png"]]; // Any image in Xcode project
          imageView.center = CGPointMake(100, 250);
          [imageView sizeToFit];
          [self.view addSubview:imageView];
          [self addMovementGesturesToView:imageView];
      
          // Note: Changing the font size would be crisper than zooming a font!
          UILabel *label = [[UILabel alloc] init];
          label.text = @"Hello Gestures!";
          label.font = [UIFont systemFontOfSize:30];
          label.textColor = [UIColor blackColor];
          [label sizeToFit];
          label.center = CGPointMake(100, 400);
          [self.view addSubview:label];
          [self addMovementGesturesToView:label];
      }
      
      - (void)addMovementGesturesToView:(UIView *)view {
          view.userInteractionEnabled = YES;  // Enable user interaction
      
          UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
          panGesture.delegate = self;
          [view addGestureRecognizer:panGesture];
      
          UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)];
          pinchGesture.delegate = self;
          [view addGestureRecognizer:pinchGesture];
      }
      


5 commentaires

Cela ne fonctionne pas à moins que la reconnaissance simultanée des gestes ne soit autorisée avec Gesurerecognizer: DROITREMONNUSEMONTHITÉE Connectez-vous: Méthode UigesurerCognizerDelegate.


dans la guérison: l'état est comparé deux fois à UigesurerecognerstatéChanged


De nombreux gestes incendient plusieurs fois dans l'UigestureConfortstatéChased. Lisez les guides sur les événements pour iOS: développeur.apple.com/library/ios/#documentation/eventhingling / ...


La référence de la classe est également emballée avec de superbes informations: développeur.apple.com/library/ios/#documentation/uikit/referen CE / ...


Je pense que vous avez mal compris le commentaire de Klaas, dans la déclaration IF, l'État a été comparé à deux reprises à UigesurerecOnStatChanganged. J'ai édité votre réponse pour enlever l'une des comparaisons.



2
votes

Si quelqu'un est intéressé par une implémentation rapide de cette utilisation du métal pour faire le rendu, j'ai un projet disponible ici .


1 commentaires

Bonjour Tyler, il n'a pas de pincée pour faire pivoter la fonction.



1
votes

Swift

Merci beaucoup à Paul !!! Voici sa version Swift: xxx

démo (sur simulateur):

 Entrez la description de l'image ici


1 commentaires

OMG merci je gaspillé beaucoup trop d'heures à ce sujet.