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?
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
- (void)viewDidLoad {
[super viewDidLoad];
for(UIView* v in self.view.subviews)
{
if([v isKindOfClass:[UIButton class]])
{
UIButton* btn = (UIButton*)v;
[btn setExclusiveTouch:YES];
}
}
}
- (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.
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.
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;
}
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.
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
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.
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
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.
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
}
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
...
}
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
}
}
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];
}
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
}
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.
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;
}
------
------
}