42 votes

Défilement à deux doigts avec un UIScrollView

J'ai une application où ma vue principale accepte les deux touchesBegan y touchesMoved et, par conséquent, il peut être touché d'un seul doigt et traîné. Je veux mettre en place un UIScrollView J'ai réussi à le faire fonctionner, mais il remplace les drags, et donc mon ContentView ne les reçoit jamais. J'aimerais mettre en place un UIScrollview où un glissement de deux doigts indique un défilement, et un événement de glissement d'un doigt est transmis à ma vue de contenu, de sorte qu'elle fonctionne normalement. Dois-je créer ma propre sous-classe de UIScrollView ?

Voici le code de mon appDelegate où j'implémente le UIScrollView .

@implementation MusicGridAppDelegate

@synthesize window;
@synthesize viewController;
@synthesize scrollView;

- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    // Override point for customization after app launch    
    //[application setStatusBarHidden:YES animated:NO];
    //[window addSubview:viewController.view];

    scrollView.contentSize = CGSizeMake(720, 480);
    scrollView.showsHorizontalScrollIndicator = YES;
    scrollView.showsVerticalScrollIndicator = YES;
    scrollView.delegate = self;
    [scrollView addSubview:viewController.view];
    [window makeKeyAndVisible];
}

- (void)dealloc {
    [viewController release];
    [scrollView release];
    [window release];
    [super dealloc];
}

64voto

Kenshi Points 521

Dans le SDK 3.2, la gestion du toucher pour UIScrollView est gérée à l'aide de dispositifs de reconnaissance des gestes.

Si vous voulez faire un panoramique à deux doigts au lieu du panoramique à un doigt par défaut, vous pouvez utiliser le code suivant :

for (UIGestureRecognizer *gestureRecognizer in scrollView.gestureRecognizers) {     
    if ([gestureRecognizer  isKindOfClass:[UIPanGestureRecognizer class]]) {
        UIPanGestureRecognizer *panGR = (UIPanGestureRecognizer *) gestureRecognizer;
        panGR.minimumNumberOfTouches = 2;               
    }
}

39voto

Guto Araujo Points 1438

Pour iOS 5+, la définition de cette propriété a le même effet que la réponse de Mike Laurence :

self.scrollView.panGestureRecognizer.minimumNumberOfTouches = 2;

Le déplacement d'un doigt est ignoré par panGestureRecognizer et l'événement de déplacement d'un doigt est donc transmis à la vue du contenu.

14voto

Mike Laurence Points 192

Dans iOS 3.2+, il est désormais possible d'obtenir un défilement à deux doigts assez facilement. Il suffit d'ajouter une fonction de reconnaissance des gestes de défilement à la vue défilante et de définir sa valeur maximale (MaximumNumberOfTouches) sur 1. Elle revendiquera tous les défilements à un seul doigt, mais permettra aux défilements à deux doigts ou plus de remonter la chaîne jusqu'à la fonction intégrée de reconnaissance des gestes de défilement de la vue défilante (et donc de permettre un défilement normal).

UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(recognizePan:)];
panGestureRecognizer.maximumNumberOfTouches = 1;
[scrollView addGestureRecognizer:panGestureRecognizer];
[panGestureRecognizer release];

10voto

Andrey Tarantsov Points 4487

Vous devez sous-classer UIScrollView (bien sûr !). Ensuite, vous devez :

  • faire des événements d'un seul doigt pour aller à votre vue de contenu (facile), et

  • faire défiler les événements à deux doigts dans la vue de défilement (peut être facile, peut être difficile, peut être impossible).

La suggestion de Patrick est généralement bonne : faites en sorte que votre sous-classe UIScrollView connaisse votre vue de contenu, puis dans les gestionnaires d'événements de toucher, vérifiez le nombre de doigts et transmettez l'événement en conséquence. Veillez simplement à ce que (1) les événements que vous envoyez à la vue du contenu ne soient pas renvoyés à UIScrollView par la chaîne du répondeur (c'est-à-dire assurez-vous de les traiter tous), (2) respectez le flux habituel des événements de toucher (c'est-à-dire touchesBegan, puis un certain nombre de {touchesBegan, touchesMoved, touchesEnded}, terminé par touchesEnded ou touchesCancelled), en particulier lorsque vous traitez avec UIScrollView. #Le numéro 2 peut être délicat.

Si vous décidez que l'événement est destiné à UIScrollView, une autre astuce consiste à faire croire à UIScrollView que votre geste à deux doigts est en fait un geste à un doigt (car UIScrollView ne peut pas être défilé avec deux doigts). Essayez de ne transmettre à super que les données relatives à un seul doigt (en filtrant l'événement (NSSet *)touches (notez qu'il ne contient que les touches modifiées et ignore complètement les événements pour le mauvais doigt).

Si cela ne fonctionne pas, vous avez des problèmes. Théoriquement, vous pouvez essayer de créer des touches artificielles pour alimenter UIScrollView en créant une classe qui ressemble à UITouch. Le code C sous-jacent ne vérifie pas les types, donc peut-être que le casting (YourTouch *) en (UITouch *) fonctionnera, et vous serez en mesure de tromper UIScrollView en gérant les touches qui ne se sont pas réellement produites.

Vous voulez probablement lire mon article sur les astuces avancées de UIScrollView (et y voir un exemple de code UIScrollView sans aucun rapport).

Bien sûr, si vous n'arrivez pas à le faire fonctionner, vous avez toujours la possibilité de contrôler manuellement le mouvement de UIScrollView ou d'utiliser une vue de défilement entièrement personnalisée. La classe TTScrollView se trouve dans la section Bibliothèque Three20 il n'est pas agréable pour l'utilisateur, mais il l'est pour le programmeur.

8voto

Yar Points 25421

Les réponses sont confuses car on ne peut trouver la bonne réponse qu'en lisant toutes les autres réponses et les commentaires (la réponse la plus proche a posé la question à l'envers). La réponse acceptée est trop vague pour être utile, et suggère une méthode différente.

Synthèse, cela fonctionne

    // makes it so that only two finger scrolls go
    for (id gestureRecognizer in self.gestureRecognizers) {     
        if ([gestureRecognizer  isKindOfClass:[UIPanGestureRecognizer class]])
        {
            UIPanGestureRecognizer *panGR = gestureRecognizer;
            panGR.minimumNumberOfTouches = 2;              
            panGR.maximumNumberOfTouches = 2;
        }
    }   

Cela nécessite deux doigts pour un défilement. Je l'ai fait dans une sous-classe, mais si ce n'est pas le cas, remplacez simplement self.gestureRecognizers con myScrollView.gestureRecognizers et vous êtes prêt à partir.

La seule chose que j'ai ajoutée est d'utiliser id pour éviter un casting moche :)

Cela fonctionne mais peut devenir assez compliqué si vous voulez que votre UIScrollView fasse aussi du zoom... les gestes ne fonctionnent pas correctement, puisque le pinch-to-zoom et le scroll se disputent. Je mettrai à jour cette page si je trouve une réponse appropriée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X