Je veux réagir quand quelqu'un secoue l'iPhone. Je ne me soucie pas particulièrement de la façon dont ils le secouent, juste qu'il a été agité vigoureusement pendant une fraction de seconde. Quelqu'un sait-il comment détecter cela?
la source
Je veux réagir quand quelqu'un secoue l'iPhone. Je ne me soucie pas particulièrement de la façon dont ils le secouent, juste qu'il a été agité vigoureusement pendant une fraction de seconde. Quelqu'un sait-il comment détecter cela?
Dans 3.0, il existe désormais un moyen plus simple: connectez-vous aux nouveaux événements de mouvement.
L'astuce principale est que vous devez avoir certains UIView (pas UIViewController) que vous souhaitez que firstResponder reçoive les messages d'événement shake. Voici le code que vous pouvez utiliser dans n'importe quelle UIView pour obtenir des événements de secousse:
@implementation ShakingView
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if ( event.subtype == UIEventSubtypeMotionShake )
{
// Put in code here to handle shake
}
if ( [super respondsToSelector:@selector(motionEnded:withEvent:)] )
[super motionEnded:motion withEvent:event];
}
- (BOOL)canBecomeFirstResponder
{ return YES; }
@end
Vous pouvez facilement transformer n'importe quelle UIView (même les vues système) en une vue qui peut obtenir l'événement shake simplement en sous-classant la vue avec uniquement ces méthodes (puis en sélectionnant ce nouveau type au lieu du type de base dans IB, ou en l'utilisant lors de l'allocation d'un vue).
Dans le contrôleur de vue, vous souhaitez définir cette vue pour devenir le premier répondant:
- (void) viewWillAppear:(BOOL)animated
{
[shakeView becomeFirstResponder];
[super viewWillAppear:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
[shakeView resignFirstResponder];
[super viewWillDisappear:animated];
}
N'oubliez pas que si vous avez d'autres vues qui deviennent le premier répondant des actions de l'utilisateur (comme une barre de recherche ou un champ de saisie de texte), vous devrez également restaurer l'état de premier répondant de la vue tremblante lorsque l'autre vue démissionne!
Cette méthode fonctionne même si vous définissez applicationSupportsShakeToEdit sur NO.
viewDidAppear
lieu deviewWillAppear
. Je ne sais pas pourquoi; peut-être que la vue doit être visible avant de pouvoir faire ce qu'elle fait pour commencer à recevoir les événements de tremblement?motionEnded
avant que le tremblement ne se soit réellement arrêté. Donc, en utilisant cette approche, vous obtenez une série décousue de secousses courtes au lieu d'une longue. L'autre réponse fonctionne beaucoup mieux dans ce cas.[super respondsToSelector:
ne fera pas ce que vous voulez, car c'est équivalent à appeler[self respondsToSelector:
qui reviendraYES
. Ce dont vous avez besoin, c'est[[ShakingView superclass] instancesRespondToSelector:
.Depuis mon application Diceshaker :
L'histérèse empêche l'événement de tremblement de se déclencher plusieurs fois jusqu'à ce que l'utilisateur arrête le tremblement.
la source
motionBegan
et lesmotionEnded
événements ne sont pas très précis ni précis en termes de détection du début et de la fin exacts d'un tremblement. Cette approche vous permet d'être aussi précis que vous le souhaitez.Je l'ai finalement fait fonctionner en utilisant des exemples de code de ce didacticiel Undo / Redo Manager .
C'est exactement ce que vous devez faire:
la source
applicationSupportsShakeToEdit
estYES
.[self resignFirstResponder];
avance[super viewWillDisappear:animated];
? Cela semble particulier.Tout d'abord, la réponse de Kendall du 10 juillet est parfaite.
Maintenant ... Je voulais faire quelque chose de similaire (dans l'iPhone OS 3.0+), seulement dans mon cas, je le voulais à l'échelle de l'application afin de pouvoir alerter différentes parties de l'application en cas de tremblement. Voici ce que j'ai fini par faire.
Tout d'abord, j'ai sous- classé UIWindow . C'est facile. Créez un nouveau fichier de classe avec une interface telle que
MotionWindow : UIWindow
(n'hésitez pas à choisir le vôtre, natch). Ajoutez une méthode comme ceci:Modifiez
@"DeviceShaken"
le nom de notification de votre choix. Enregistrez le fichier.Maintenant, si vous utilisez un MainWindow.xib (élément de modèle Xcode stock), allez-y et changez la classe de votre objet Window de UIWindow en MotionWindow ou tout ce que vous avez appelé. Enregistrez le xib. Si vous configurez UIWindow par programme, utilisez plutôt votre nouvelle classe Window.
Maintenant, votre application utilise la classe spécialisée UIWindow . Partout où vous voulez être informé d'une secousse, inscrivez-vous pour les notifications! Comme ça:
Pour vous retirer en tant qu'observateur:
J'ai mis le mien dans viewWillAppear: et viewWillDisappear: en ce qui concerne les contrôleurs de vue. Assurez-vous que votre réponse à l'événement shake sait s'il est "déjà en cours" ou non. Sinon, si l'appareil est secoué deux fois de suite, vous aurez un embouteillage limité. De cette façon, vous pouvez ignorer les autres notifications jusqu'à ce que vous ayez vraiment fini de répondre à la notification d'origine.
Aussi: Vous pouvez choisir de repérer motionBegan vs motionEnded . C'est à vous. Dans mon cas, l'effet doit toujours avoir lieu après que l'appareil est au repos (vs quand il commence à trembler), donc j'utilise motionEnded . Essayez les deux et voyez lequel a le plus de sens ... ou détectez / notifiez les deux!
Une autre observation (curieuse?) Ici: Remarquez qu'il n'y a aucun signe de gestion des premiers intervenants dans ce code. Je n'ai essayé cela qu'avec les contrôleurs de vue de table jusqu'à présent et tout semble fonctionner très bien ensemble! Je ne peux cependant pas garantir d'autres scénarios.
Kendall, et. al - quelqu'un peut-il expliquer pourquoi cela pourrait être le cas pour les sous-classes UIWindow ? Est-ce parce que la fenêtre est au sommet de la chaîne alimentaire?
la source
Je suis tombé sur ce post à la recherche d'une implémentation "tremblante". La réponse de millenomi a bien fonctionné pour moi, même si je cherchais quelque chose qui nécessitait un peu plus d '"action tremblante" pour se déclencher. J'ai remplacé la valeur booléenne par un entier shakeCount. J'ai également réimplémenté la méthode L0AccelerationIsShaking () dans Objective-C. Vous pouvez modifier la quantité de secousses requise en modifiant la quantité ajoutée à shakeCount. Je ne suis pas sûr d'avoir encore trouvé les valeurs optimales, mais cela semble bien fonctionner jusqu'à présent. J'espère que cela aide quelqu'un:
PS: J'ai défini l'intervalle de mise à jour au 1 / 15e de seconde.
la source
Vous devez vérifier l'accéléromètre via accelerometer: didAccelerate: méthode qui fait partie du protocole UIAccelerometerDelegate et vérifier si les valeurs dépassent un seuil pour la quantité de mouvement nécessaire pour une secousse.
Il y a un exemple de code décent dans l'accéléromètre: didAccelerate: méthode tout en bas d'AppController.m dans l'exemple GLPaint qui est disponible sur le site des développeurs iPhone.
la source
Dans iOS 8.3 (peut-être plus tôt) avec Swift, c'est aussi simple que de remplacer les méthodes
motionBegan
oumotionEnded
dans votre contrôleur de vue:la source
Voici le code délégué de base dont vous avez besoin:
Définissez également le dans le code approprié dans l'interface. c'est à dire:
@interface MyViewController: UIViewController <UIPickerViewDelegate, UIPickerViewDataSource, UIAccelerometerDelegate>
la source
Consultez l'exemple GLPaint.
http://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html
la source
Ajouter les méthodes suivantes dans le fichier ViewController.m, son fonctionnement correctement
la source
Désolé de poster ceci comme réponse plutôt que comme commentaire mais comme vous pouvez le voir, je suis nouveau sur Stack Overflow et je ne suis donc pas encore assez réputé pour poster des commentaires!
Quoi qu'il en soit, j'appuie @cire à m'assurer de définir le statut du premier répondant une fois que la vue fait partie de la hiérarchie des vues. Ainsi, la définition du statut de premier répondant dans votre
viewDidLoad
méthode de contrôleur de vue ne fonctionnera pas par exemple. Et si vous ne savez pas si cela fonctionne,[view becomeFirstResponder]
vous obtenez un booléen que vous pouvez tester.Autre point: vous pouvez utiliser un contrôleur de vue pour capturer l'événement shake si vous ne voulez pas créer inutilement une sous-classe UIView. Je sais que ce n'est pas très compliqué, mais l'option est toujours là. Déplacez simplement les extraits de code que Kendall a mis dans la sous-classe UIView dans votre contrôleur et envoyez les messages
becomeFirstResponder
etresignFirstResponder
à laself
place de la sous-classe UIView.la source
Tout d'abord, je sais que c'est un ancien poste, mais il est toujours pertinent, et j'ai trouvé que les deux réponses les plus votées n'ont pas détecté la secousse le plus tôt possible . Voici comment faire:
Dans votre ViewController:
la source
La solution la plus simple consiste à dériver une nouvelle fenêtre racine pour votre application:
Ensuite, dans votre délégué d'application:
Si vous utilisez un Storyboard, cela peut être plus délicat, je ne connais pas précisément le code dont vous aurez besoin dans le délégué d'application.
la source
@implementation
depuis le Xcode 5.Utilisez simplement ces trois méthodes pour le faire
pour plus de détails, vous pouvez vérifier un exemple de code complet là-bas
la source
Une version swiftease basée sur la toute première réponse!
la source
Pour activer cette application à l'échelle, j'ai créé une catégorie sur UIWindow:
la source