Jak mám rozpoznat, když někdo třese iPhone?

hlasů
336

Chci reagovat, když někdo třese iPhone. Nemám nijak zvlášť pečovat, jak to chvění, jen to, že byl mával prudce asi na zlomek sekundy. Ví někdo, jak se to zjistí?

Položena 29/09/2008 v 21:14
zdroj uživatelem
V jiných jazycích...                            


16 odpovědí

Odpovězeno 29/09/2008 v 21:16
zdroj uživatelem

hlasů
12

Je třeba zkontrolovat akcelerometru pomocí akcelerometru: didAccelerate: metodu, která je součástí protokolu UIAccelerometerDelegate a zkontrolujte, zda jsou hodnoty jdou nad prahem pro množství pohybu potřebného pro chvění.

K dispozici je slušná ukázkový kód v akcelerometru: didAccelerate: metoda vpravo v dolní části AppController.m v příkladu GLPaint, který je k dispozici na webu pro vývojáře pro zařízení iPhone.

Odpovězeno 29/09/2008 v 22:17
zdroj uživatelem

hlasů
179

Z mého Diceshaker aplikace:

// Ensures the shake is strong enough on at least two axes before declaring it a shake.
// "Strong enough" means "greater than a client-supplied threshold" in G's.
static BOOL L0AccelerationIsShaking(UIAcceleration* last, UIAcceleration* current, double threshold) {
    double
        deltaX = fabs(last.x - current.x),
        deltaY = fabs(last.y - current.y),
        deltaZ = fabs(last.z - current.z);

    return
        (deltaX > threshold && deltaY > threshold) ||
        (deltaX > threshold && deltaZ > threshold) ||
        (deltaY > threshold && deltaZ > threshold);
}

@interface L0AppDelegate : NSObject <UIApplicationDelegate> {
    BOOL histeresisExcited;
    UIAcceleration* lastAcceleration;
}

@property(retain) UIAcceleration* lastAcceleration;

@end

@implementation L0AppDelegate

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    [UIAccelerometer sharedAccelerometer].delegate = self;
}

- (void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {

    if (self.lastAcceleration) {
        if (!histeresisExcited && L0AccelerationIsShaking(self.lastAcceleration, acceleration, 0.7)) {
            histeresisExcited = YES;

            /* SHAKE DETECTED. DO HERE WHAT YOU WANT. */

        } else if (histeresisExcited && !L0AccelerationIsShaking(self.lastAcceleration, acceleration, 0.2)) {
            histeresisExcited = NO;
        }
    }

    self.lastAcceleration = acceleration;
}

// and proper @synthesize and -dealloc boilerplate code

@end

Hystereze brání událost chvění od spuštění vícekrát, dokud uživatel přestane třást.

Odpovězeno 01/10/2008 v 21:43
zdroj uživatelem

hlasů
33

Narazil jsem na tento post hledá „třepání“ realizaci. millenomi odpověď pracoval i pro mě, když jsem hledal něco, co požadovanou trochu více „třesoucí se akce“ pro spuštění. Jsem nahradí se logická hodnota s int shakeCount. Také reimplemented metody L0AccelerationIsShaking () v Objective-C. Můžete vyladit ammount otřesů požaduje laděním ammount přidán shakeCount. Nejsem si jistá, že jsem zjistil, že optimální hodnoty ještě, ale zdá se, že funguje dobře tak daleko. Doufám, že to někomu pomůže:

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
    if (self.lastAcceleration) {
        if ([self AccelerationIsShakingLast:self.lastAcceleration current:acceleration threshold:0.7] && shakeCount >= 9) {
            //Shaking here, DO stuff.
            shakeCount = 0;
        } else if ([self AccelerationIsShakingLast:self.lastAcceleration current:acceleration threshold:0.7]) {
            shakeCount = shakeCount + 5;
        }else if (![self AccelerationIsShakingLast:self.lastAcceleration current:acceleration threshold:0.2]) {
            if (shakeCount > 0) {
                shakeCount--;
            }
        }
    }
    self.lastAcceleration = acceleration;
}

- (BOOL) AccelerationIsShakingLast:(UIAcceleration *)last current:(UIAcceleration *)current threshold:(double)threshold {
    double
    deltaX = fabs(last.x - current.x),
    deltaY = fabs(last.y - current.y),
    deltaZ = fabs(last.z - current.z);

    return
    (deltaX > threshold && deltaY > threshold) ||
    (deltaX > threshold && deltaZ > threshold) ||
    (deltaY > threshold && deltaZ > threshold);
}

PS: Já jsem nastavit interval aktualizace na 1 / 15th sekundy.

[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / 15)];
Odpovězeno 10/11/2008 v 18:14
zdroj uživatelem

hlasů
9

Jedná se o základní delegát kód budete potřebovat:

#define kAccelerationThreshold      2.2

#pragma mark -
#pragma mark UIAccelerometerDelegate Methods
    - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration 
    {   
        if (fabsf(acceleration.x) > kAccelerationThreshold || fabsf(acceleration.y) > kAccelerationThreshold || fabsf(acceleration.z) > kAccelerationThreshold) 
            [self myShakeMethodGoesHere];   
    }

Také nastavit v příslušném kódu v rozhraní. tj:

@interface MyViewController: UIViewController <UIPickerViewDelegate, UIPickerViewDataSource, UIAccelerometerDelegate>

Odpovězeno 22/03/2009 v 22:15
zdroj uživatelem

hlasů
292

V 3.0, tam je nyní jednodušší způsob - háček do nových pohybových akcích.

Hlavní trik je, že musíte mít nějaké UIView (ne UIViewController), který chcete použít jako firstResponder pro příjem zpráv shake událostí. Zde je kód, který můžete použít v libovolném UIView dostat shake události:

@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

Můžete snadno převést jakýkoli UIView (i názory System) do názoru, že může dostat událost zatřesení pouhým subclassing názor pouze těmito metodami (a výběrem tento nový typ namísto základního typu v IB, nebo jej používáte při přidělování Pohled).

V kontroleru pohledu, který chcete nastavit tento pohled se stal první pomoci:

- (void) viewWillAppear:(BOOL)animated
{
    [shakeView becomeFirstResponder];
    [super viewWillAppear:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
    [shakeView resignFirstResponder];
    [super viewWillDisappear:animated];
}

Nezapomeňte, že pokud máte jiné názory, které se stanou první pomoci od uživatelských akcí (jako panel vyhledávání nebo pole pro zadávání textu), budete také muset obnovit třepání zobrazit stav první pomoci, když je druhý pohled rezignuje!

Tato metoda funguje, i když nastavíte applicationSupportsShakeToEdit na NO.

Odpovězeno 10/07/2009 v 22:06
zdroj uživatelem

hlasů
5

Omlouvám se, že tento post jako spíše než odpověď komentář, ale jak vidíte Jsem nový přetečení zásobníku a tak jsem dosud dostatečně seriózní možnost psaní komentářů se!

Každopádně jsem druhý @cire o tom, ujistěte se, že nastavení prvního stavu odpovídač jakmile pohled je součástí hierarchie zobrazení. Takže nastavení prvního stavového odpovídače podle Vašeho názoru regulátorů viewDidLoadmetody nebude fungovat např. A pokud si nejste jisti, zda to funguje [view becomeFirstResponder]vrátíme logický si můžete vyzkoušet.

Další bod: vy můžete použít ovladač zobrazení zachytit událost chvění, pokud nechcete vytvářet UIView podtřídy zbytečně. Vím, že to není tak moc potíží, ale stále možnost existuje. Jen přesunout kousky kódu, které Kendall dát do UIView podtřídy do řídicí jednotky a odeslat becomeFirstRespondera resignFirstResponderzprávy na selfmísto UIView podtřídy.

Odpovězeno 18/08/2009 v 16:05
zdroj uživatelem

hlasů
94

Za prvé, Kendall 10.července odpověď je spot-on.

Teď ... Chtěl jsem udělat něco podobného (v iPhone OS 3.0 nebo vyšší), jen v mém případě jsem chtěl, aby to app-široký, takže jsem mohl upozornit různých částí aplikace, kdy došlo k chvění. Tady je to, co jsem skončil dělat.

Za prvé, podtřídy I UIWindow . To je snadná peasy. Vytvořte nový soubor třídy s rozhraním, jako je MotionWindow : UIWindow(nebojte se vybrat si vlastní, tutovka). Přidání metody jako tak:

- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
    if (event.type == UIEventTypeMotion && event.subtype == UIEventSubtypeMotionShake) {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"DeviceShaken" object:self];
    }
}

Změnu @"DeviceShaken"názvu oznamovací povinnosti podle svého výběru. Uložení souboru.

Nyní, pokud použijete MainWindow.xib (legální Xcode šablona věci), tam jít a změnit třída vašeho objektu Window z UIWindow na MotionWindow nebo jak se to jmenuje. Uložení XIb. Pokud nastavíte UIWindow programově, použijte novou třídu Window tam místo.

Nyní je aplikace pomocí specializovaného UIWindow třídu. Všude tam, kde chcete být řečeno o chvění, zaregistrovat pro ně oznámení! Takhle:

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(deviceShaken) name:@"DeviceShaken" object:nil];

Chcete-li odstranit sami sebe jako pozorovatel:

[[NSNotificationCenter defaultCenter] removeObserver:self];

Dal jsem důl v viewWillAppear: a viewWillDisappear: jde-li o View kontroléry. Ujistěte se, že vaše reakce na události shake ví, jestli to je „už probíhá“, nebo ne. V opačném případě, je-li přístroj třepe dvakrát za sebou, budete mít Li'l dopravní zácpy. Tímto způsobem můžete ignorovat další oznámení, až budete skutečně udělat v reakci na původní oznámení.

Také: Můžete si zvolit, aby cue pryč motionBegan vs. motionEnded . Je to na tobě. V mém případě je účinek stále potřebuje uskutečnit poté, co je zařízení v klidovém stavu (vs. kdy se začíná třást), takže já používám motionEnded . Zkuste oba a uvidíte, který z nich má větší smysl ... nebo detekci / upozorňovat na obou!

Ještě jeden (? Zvědavý) pozorování zde: Všimněte si, nic nenasvědčuje tomu, první vedení odpovídač v tomto kódu. Snažil jsem se jen to s Table View kontroléry tak daleko a všechno se zdá fungovat docela pěkně pohromadě! Nemohu ručit za jiné scénáře ačkoli.

Kendall et. al - může někdo mluvit, proč by to mohlo být tak pro UIWindow podtřídy? Je to proto, že okno je na vrcholu potravního řetězce?

Odpovězeno 29/08/2009 v 14:47
zdroj uživatelem

hlasů
154

Nakonec jsem to funguje pomocí příkladů kódu z této Undo / Redo Správce Tutorial .
To je přesně to, co je třeba udělat:

  • Nastavit applicationSupportsShakeToEdit vlastnictví na App delegáta:
  • 
        - (void)applicationDidFinishLaunching:(UIApplication *)application {
    
            application.applicationSupportsShakeToEdit = YES;
    
            [window addSubview:viewController.view];
            [window makeKeyAndVisible];
    }
    

  • Přidat / Přepsat canBecomeFirstResponder , viewDidAppear: a viewWillDisappear: způsoby podle vašeho názoru Controller:
  • 
    -(BOOL)canBecomeFirstResponder {
        return YES;
    }
    
    -(void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        [self becomeFirstResponder];
    }
    
    - (void)viewWillDisappear:(BOOL)animated {
        [self resignFirstResponder];
        [super viewWillDisappear:animated];
    }
    

  • Přidejte motionEnded metodu ke svému View Controller:
  • 
    - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
    {
        if (motion == UIEventSubtypeMotionShake)
        {
            // your code
        }
    }
    
    Odpovězeno 09/03/2010 v 00:58
    zdroj uživatelem

    hlasů
    7

    Přidejte následující metody v souboru ViewController.m, jeho správnou funkci

        -(BOOL) canBecomeFirstResponder
        {
             /* Here, We want our view (not viewcontroller) as first responder 
             to receive shake event message  */
    
             return YES;
        }
    
        -(void) motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
        {
                if(event.subtype==UIEventSubtypeMotionShake)
                {
                        // Code at shake event
    
                        UIAlertView *alert=[[UIAlertView alloc] initWithTitle:@"Motion" message:@"Phone Vibrate"delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
                        [alert show];
                        [alert release];
    
                        [self.view setBackgroundColor:[UIColor redColor]];
                 }
        }
        - (void)viewDidAppear:(BOOL)animated
        {
                 [super viewDidAppear:animated];
                 [self becomeFirstResponder];  // View as first responder 
         }
    
    Odpovězeno 15/10/2012 v 13:11
    zdroj uživatelem

    hlasů
    1

    Stačí použít tyto tři způsoby, jak to udělat

    - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{
    - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event{
    - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{
    

    Podrobnosti si můžete zkontrolovat kompletní příklad kódu přes zde

    Odpovězeno 21/02/2013 v 10:30
    zdroj uživatelem

    hlasů
    3

    Nejjednodušším řešením je odvodit nový kořenový okno pro aplikace:

    @implementation OMGWindow : UIWindow
    
    - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
        if (event.type == UIEventTypeMotion && motion == UIEventSubtypeMotionShake) {
            // via notification or something   
        }
    }
    @end
    

    Pak se v aplikačním delegáta:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        self.window = [[OMGWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        //…
    }
    

    Pokud používáte storyboard, může to být složitější, nevím kód budete potřebovat v aplikačním delegáta přesně.

    Odpovězeno 12/07/2014 v 13:46
    zdroj uživatelem

    hlasů
    4

    Za prvé, vím, že to je stará pošta, ale je to stále aktuální, a zjistil jsem, že dva největší hlasoval odpovědi ani detekovat otřesy co nejdříve . To je, jak na to:

    1. Link CoreMotion do projektu sestavení fázích cílové je: CoreMotion
    2. Ve vašem ViewController:

      - (BOOL)canBecomeFirstResponder {
          return YES;
      }
      
      - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
      {
          if (motion == UIEventSubtypeMotionShake) {
              // Shake detected.
          }
      }
      
    Odpovězeno 13/03/2015 v 14:59
    zdroj uživatelem

    hlasů
    11

    V systému iOS 8.3 (možná starší) s Swift, je to tak jednoduché, jak přepsání motionBegannebo motionEndedzpůsoby podle vašeho názoru regulátor:

    class ViewController: UIViewController {
        override func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent) {
            println("started shaking!")
        }
    
        override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent) {
            println("ended shaking!")
        }
    }
    
    Odpovězeno 20/04/2015 v 22:39
    zdroj uživatelem

    hlasů
    1

    Verze swiftease založený na úplně první odpověď!

    override func motionEnded(_ motion: UIEventSubtype, with event: UIEvent?) {
        if ( event?.subtype == .motionShake )
        {
            print("stop shaking me!")
        }
    }
    
    Odpovězeno 10/09/2017 v 07:44
    zdroj uživatelem

    hlasů
    -1

    Chcete-li tuto aplikaci-široký, jsem vytvořil kategorii UIWindow:

    @implementation UIWindow (Utils)
    
    - (BOOL)canBecomeFirstResponder
    {
        return YES;
    }
    
    - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
    {
        if (motion == UIEventSubtypeMotionShake) {
            // Do whatever you want here...
        }
    }
    
    @end
    
    Odpovězeno 15/09/2017 v 19:45
    zdroj uživatelem

    Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more