web-dev-qa-db-fra.com

Comment désactiver le multitouch?

Mon application comporte plusieurs boutons qui déclenchent différents événements. L'utilisateur ne doit PAS pouvoir maintenir plusieurs boutons enfoncés. Quoi qu'il en soit, maintenir plusieurs boutons enfoncés bloque l'application.

Et oui, j'essaie de désactiver le multi-touch dans mon application.

J'ai décoché 'Multiple Touch' dans tous les fichiers xib et, autant que je sache, les propriétés 'multipleTouchEnabled' et 'exclusiveTouch' contrôlent si la vue utilise le multitouch. Donc, dans mon applicationDidFinishLaunching j'ai mis ceci:

self.mainViewController.view.multipleTouchEnabled=NO;
self.mainViewController.view.exclusiveTouch =YES;

Et dans chacun de mes contrôleurs de vue, j'ai mis ceci dans le viewDidLoad

self.view.multipleTouchEnabled=NO;
self.view.exclusiveTouch=YES;

Cependant, il encore accepte plusieurs touches. Je pourrais faire quelque chose comme désactiver d'autres boutons après avoir touché un événement, mais ce serait un vilain bidouillage. Il existe sûrement un moyen de désactiver correctement le multi-touch?

34
cannyboy

Si vous souhaitez qu'un seul bouton réponde à des effleurements à la fois, vous devez définir exclusiveTouch pour ce bouton plutôt que pour la vue parent. Alternativement, vous pouvez désactiver les autres boutons lorsqu'un bouton obtient l'événement "Touch Down".


Voici un exemple de ce dernier, qui a mieux fonctionné lors de mes tests. La définition de exclusiveTouch pour les boutons a fonctionné, mais a entraîné des problèmes intéressants lorsque vous avez déplacé le doigt du bord d’un bouton au lieu de simplement cliquer dessus.

Vous devez disposer de prises dans votre contrôleur reliées à chaque bouton, ainsi que des événements "Toucher vers le bas", "Retouche à l'intérieur" et "Retouche à l'extérieur" aux méthodes appropriées de votre contrôleur.

#import "multibuttonsViewController.h"

@implementation multibuttonsViewController

// hook this up to "Touch Down" for each button
- (IBAction) pressed: (id) sender
{
    if (sender == one)
    {
        two.enabled = false;
        three.enabled = false;
        [label setText: @"One"]; // or whatever you want to do
    }
    else if (sender == two)
    {
        one.enabled = false;
        three.enabled = false;
        [label setText: @"Two"];  // or whatever you want to do
    }
    else
    {
        one.enabled = false;
        two.enabled = false;
        [label setText: @"Three"];  // or whatever you want to do
    }
}

// hook this up to "Touch Up Inside" and "Touch Up Outside"
- (IBAction) released: (id) sender
{
    one.enabled = true;
    two.enabled = true;
    three.enabled = true;
}

@end
44
Mark Bessey
- (void)viewDidLoad {
    [super viewDidLoad];

    for(UIView* v in self.view.subviews)
    {
        if([v isKindOfClass:[UIButton class]])
        {
            UIButton* btn = (UIButton*)v;
            [btn setExclusiveTouch:YES];
        }
    }
}
21
neoevoke
- (void)viewDidLoad {
    [super viewDidLoad];

    for(UIView* v in self.view.subviews)
    {
        if([v isKindOfClass:[UIButton class]])
        {
            UIButton* btn = (UIButton*)v;
            [btn setExclusiveTouch:YES];
        }
    }
}

Ce code est testé et fonctionne parfaitement pour moi. Il n'y a pas de blocage d'application lorsque vous appuyez sur plus d'un bouton à la fois.

5
Parth Mehta

Sur la base de la réponse de neoevoke, ne l'améliorant qu'un peu pour qu'il vérifie également les enfants des sous-vues, j'ai créé cette fonction et l'a ajoutée à mon fichier utils: 

// Set exclusive touch to all children

+ (void)setExclusiveTouchToChildrenOf:(NSArray *)subviews
{
    for (UIView *v in subviews) {
        [self setExclusiveTouchToChildrenOf:v.subviews];
        if ([v isKindOfClass:[UIButton class]]) {
            UIButton *btn = (UIButton *)v;
            [btn setExclusiveTouch:YES];
        }
    }
}

Ensuite, un simple appel à:

[Utils setExclusiveTouchToChildrenOf:self.view.subviews];

... fera l'affaire.

3
h4lc0n

C’est un problème assez souvent signalé par nos testeurs. L’une des approches que j’utilise parfois, même si elle doit être utilisée consciemment, consiste à créer une catégorie pour UIView, comme celle-ci:

@implementation UIView (ExclusiveTouch)

- (BOOL)isExclusiveTouch
{
    return YES;
}
3
Krodak

Votre application se bloque pour une raison. Enquêter plus avant, utiliser le débogueur, voir ce qui ne va pas au lieu d'essayer de cacher le bogue.

Modifier:

D'accord, d'accord, je dois admettre que j'étais un peu dur. Vous devez définir la propriété exclusiveTouch sur chaque bouton . C'est tout. La propriété multipleTouchEnabled n'est pas pertinente.

3
Nikolai Ruhe

Pour désactiver le multitouch dans Swift: 

Vous devez d’abord avoir un point de vente pour chaque bouton, puis régler la touche exclusive sur true. Par conséquent, viewDidLoad() aurait pour vous:

yourButton.exclusiveTouch = true.

// pas vraiment nécessaire mais vous pouvez aussi ajouter:

self.view.multipleTouchEnabled = false

2
Alex Zanfir

Assez simple, vous pouvez utiliser la propriété ExclusiveTouch dans ce cas.

[youBtn setExclusiveTouch:YES];

C'est une valeur booléenne qui indique si le récepteur gère exclusivement les événements tactiles.

Si vous définissez cette propriété sur YES, le récepteur bloque la diffusion des événements tactiles vers d'autres vues de la même fenêtre. La valeur par défaut de cette propriété est NO.

1
Aks

Si vous souhaitez désactiver le multi-touch dans toute l'application et ne souhaitez pas écrire de code pour chaque bouton, vous pouvez simplement utiliser le bouton Appearance of. Écrivez sous la ligne dans didFinishLaunchingWithOptions.

UIButton.appearance().isExclusiveTouch = true

C'est génial!! UIAppearance

Vous pouvez même l’utiliser pour n’importe quelle classe UIView, donc si vous souhaitez désactiver le multi-touch pour quelques boutons. Faire un bouton CustomClass puis

CustomButton.appearance().isExclusiveTouch = true

Il y a un autre avantage qui peut vous aider. Si vous souhaitez désactiver les touches multiples dans une ViewController particulière

UIButton.appearance(whenContainedInInstancesOf: [ViewController2.self]).isExclusiveTouch = true
0
TheTiger

Mon expérience est que, par défaut, un nouveau projet n'autorise même pas le multitouch, vous devez l'activer. Mais je suppose que cela dépend de la façon dont vous avez commencé. Avez-vous utilisé un exemple mutlitouch comme modèle?

Tout d’abord, êtes-vous absolument certain que le multitouch est activé? Il est possible de générer assez rapidement des touches uniques en séquence. Le multitouch concerne davantage ce que vous faites avec deux doigts ou plus une fois qu'ils sont à la surface. Peut-être que vous avez une seule touche, mais que vous ne gérez pas correctement ce qui se passe si vous appuyez sur deux boutons presque au même moment.

0
Nosredna

J'avais eu du mal à gérer certains cas étranges lorsque je glissais des objets autour d'une vue, et que si vous touchez un autre objet en même temps, la méthode toucheBegan est activée. Mon solution consistait à désactiver les interactions utilisateur pour la vue parent jusqu'à ce que touchesEnded ou TouchesCancelled soient appelées. 

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) { 
   // whatever setup you need
   self.view.userInteractionEnabled = false 
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
   // whatever setup you need
   self.view.userInteractionEnabled = true
}

override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
   // whatever setup you need
   self.view.userInteractionEnabled = true
}
0
Gaston Martin

Pour désactiver le multitouch global dans Xamarin.iOS

Copiez et collez le code ci-dessous:

[DllImport(ObjCRuntime.Constants.ObjectiveCLibrary, EntryPoint = "objc_msgSend")]
internal extern static IntPtr IntPtr_objc_msgSend(IntPtr receiver, IntPtr selector, bool isExclusiveTouch);
static void SetExclusiveTouch(bool isExclusiveTouch)
{
    var selector = new ObjCRuntime.Selector("setExclusiveTouch:");
    IntPtr_objc_msgSend(UIView.Appearance.Handle, selector.Handle, isExclusiveTouch);
}

Et définissez-le sur AppDelegate:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    ...
    SetExclusiveTouch(true); // setting exlusive to true disables the multitouch
    ...
}
0
mr5

J'ai décidé ce problème de cette façon:

NSTimeInterval intervalButtonPressed;

- (IBAction)buttonPicturePressed:(id)sender{ 

    if (([[NSDate date] timeIntervalSince1970] - intervalButtonPressed) > 0.1f) {
        intervalButtonPressed = [[NSDate date] timeIntervalSince1970];
        //your code for button
    }
}
0
Igor

J'ai créé UIView Class Extension et ajouté ces deux fonctions. et quand je veux désactiver la vue tactile, je viens d’appeler [view makeExclusiveTouch];

- (void) makeExclusiveTouchForViews:(NSArray*)views {
    for (UIView * view in views) {
        [view makeExclusiveTouch];
    }
}

- (void) makeExclusiveTouch {
    self.multipleTouchEnabled = NO;
    self.exclusiveTouch = YES;
    [self makeExclusiveTouchForViews:self.subviews];
}
0
kjhkjhkjh

Si vous souhaitez désactiver le multitouch par programme ou si vous utilisez cocos2d (pas d'option multipleTouchEnabled), vous pouvez utiliser le code suivant sur votre délégué ccTouches:

- (BOOL)ccTouchesBegan:(NSSet *)touches
 withEvent:(UIEvent *)event {
       NSSet *multiTouch = [event allTouches];
       if( [multiTouch count] > 1) { 
            return; 
       }
       else {
           //else your rest of the code  
}
0
Jonny Ramos

Je viens d'avoir exactement ce problème.

La solution que nous avons proposée consistait simplement à hériter d'une nouvelle classe d'UIButton qui remplace la méthode initWithCoder, et à l'utiliser lorsque nous avions besoin d'un bouton Push à la fois (c'est-à-dire partout):

@implementation ExclusiveButton

(id)initWithCoder: (NSCoder*)decoder 
{ 
   [self setExclusiveTouch:YES]; 
   return [super initWithCoder:decoder]
}

@end

Notez que cela ne fonctionne qu'avec les boutons chargés à partir de fichiers nib.

0
Andy Krouwel

Désactivez tous les boutons affichés dans "Touch Down" event et activez-les dans "Touch Up Inside" event.

par exemple

- (void) handleTouchDown {
    for (UIButton *btn in views) {
        btn.enable = NO;
    }
}

- (void) handleTouchUpInside {
    for (UIButton *btn in views) {
        btn.enable = Yes;
    }
    ------
    ------
}
0
Rajendra