Chcę zareagować, gdy ktoś potrząśnie iPhone'em. Nie obchodzi mnie szczególnie, jak się nim potrząsają, tylko to, że machał energicznie przez ułamek sekundy. Czy ktoś wie, jak to wykryć?
źródło
Chcę zareagować, gdy ktoś potrząśnie iPhone'em. Nie obchodzi mnie szczególnie, jak się nim potrząsają, tylko to, że machał energicznie przez ułamek sekundy. Czy ktoś wie, jak to wykryć?
W 3.0 jest teraz łatwiejszy sposób - dołącz do nowych zdarzeń ruchu.
Główną sztuczką jest to, że musisz mieć UIView (nie UIViewController), który jako pierwszy odpowiada, aby otrzymywać komunikaty o zdarzeniach wstrząsających. Oto kod, którego możesz użyć w dowolnym UIView, aby uzyskać zdarzenia wstrząsania:
@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
Możesz łatwo przekształcić dowolne UIView (nawet widoki systemowe) w widok, który może uzyskać zdarzenie wstrząśnięcia, po prostu podklasując widok tylko tymi metodami (a następnie wybierając ten nowy typ zamiast typu podstawowego w IB lub używając go podczas przydzielania widok).
W kontrolerze widoku chcesz ustawić ten widok, aby stał się pierwszą odpowiedzią:
- (void) viewWillAppear:(BOOL)animated
{
[shakeView becomeFirstResponder];
[super viewWillAppear:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
[shakeView resignFirstResponder];
[super viewWillDisappear:animated];
}
Nie zapominaj, że jeśli masz inne widoki, które stają się pierwszymi respondentami na podstawie działań użytkownika (np. Pasek wyszukiwania lub pole wprowadzania tekstu), musisz także przywrócić status pierwszego odpowiadającego widoku wstrząsającego, gdy inny widok zrezygnuje!
Ta metoda działa, nawet jeśli ustawisz applicationSupportsShakeToEdit na NIE.
viewDidAppear
zamiastviewWillAppear
. Nie jestem pewien dlaczego; może widok musi być widoczny, zanim będzie mógł zrobić wszystko, aby zacząć otrzymywać zdarzenia wstrząsania?motionEnded
zanim wstrząs rzeczywiście się zatrzyma. Tak więc, stosując to podejście, otrzymujesz rozłączną serię krótkich wstrząsów zamiast jednego długiego. Druga odpowiedź działa w tym przypadku znacznie lepiej.[super respondsToSelector:
nie zrobi tego, co chcesz, ponieważ jest to równoważne z połączeniem,[self respondsToSelector:
które powróciYES
. Potrzebujesz tego[[ShakingView superclass] instancesRespondToSelector:
.Z mojej aplikacji Diceshaker :
Histereza zapobiega wielokrotnemu wyzwalaniu zdarzenia wstrząsania, dopóki użytkownik nie zatrzyma wstrząsania.
źródło
motionBegan
imotionEnded
wydarzenia nie są bardzo precyzyjne ani dokładne pod względem wykrywania dokładnego początku i końca wstrząsu. Takie podejście pozwala być tak precyzyjnym, jak chcesz.W końcu udało mi się go uruchomić, korzystając z przykładów kodu z tego samouczka Menedżera cofania / ponawiania .
To jest dokładnie to, co musisz zrobić:
źródło
applicationSupportsShakeToEdit
jestYES
.[self resignFirstResponder];
przed[super viewWillDisappear:animated];
? To wydaje się dziwne.Po pierwsze, odpowiedź Kendalla z 10 lipca jest natychmiastowa.
Teraz ... chciałem zrobić coś podobnego (w iPhone OS 3.0+), tylko w moim przypadku chciałem, aby obejmowała całą aplikację, aby móc ostrzegać różne części aplikacji, gdy wystąpi wstrząs. Oto co skończyłem.
Najpierw podklasowałem UIWindow . To jest łatwe. Utwórz nowy plik klasy z interfejsem takim jak
MotionWindow : UIWindow
(możesz wybrać własny, natch). Dodaj taką metodę:Zmień
@"DeviceShaken"
na wybraną nazwę powiadomienia. Zapisz plik.Teraz, jeśli używasz pliku MainWindow.xib (zapasowe szablony Xcode), wejdź tam i zmień klasę swojego obiektu Window z UIWindow na MotionWindow lub jakkolwiek to nazwałeś . Zapisz xib. Jeśli skonfigurujesz UIWindow programowo , użyj tam nowej klasy Window.
Teraz Twoja aplikacja korzysta ze specjalistycznej klasy UIWindow . Gdziekolwiek chcesz otrzymywać informacje o shake'u, zarejestruj się, aby otrzymywać powiadomienia! Lubię to:
Aby usunąć siebie z roli obserwatora:
Wyświetlam mój widok WillAppear: i viewWillDisappear: przypadku kontrolerów View. Upewnij się, że Twoja reakcja na zdarzenie wstrząsowe wie, czy „już trwa”, czy nie. W przeciwnym razie, jeśli urządzenie zostanie wstrząśnięte dwa razy pod rząd, będziesz miał mały korek. W ten sposób możesz zignorować inne powiadomienia, dopóki nie skończysz odpowiadać na oryginalne powiadomienie.
Ponadto: możesz wybrać cue off z motionBegan vs. motionEnded . To zależy od Ciebie. W moim przypadku efekt zawsze musi mieć miejsce po zatrzymaniu urządzenia (w przeciwieństwie do momentu, w którym zaczyna się trząść), więc używam motionEnded . Spróbuj obu i zobacz, który z nich jest bardziej sensowny ... lub wykryj / powiadom o obu!
Jeszcze jedna (ciekawa?) Obserwacja tutaj: zauważ, że w tym kodzie nie ma śladu zarządzania pierwszą odpowiedzią. Do tej pory próbowałem tego tylko z kontrolerami widoku tabeli i wszystko wydaje się działać całkiem dobrze razem! Nie mogę jednak ręczyć za inne scenariusze.
Kendall i in. al - czy ktoś może mówić, dlaczego tak jest w przypadku podklas UIWindow ? Czy to dlatego, że okno znajduje się na górze łańcucha pokarmowego?
źródło
Natknąłem się na ten post w poszukiwaniu „wstrząsającej” implementacji. Odpowiedź millenomi działała dla mnie dobrze, chociaż szukałem czegoś, co wymagałoby nieco więcej „wstrząsania”, aby uruchomić. Zamieniłem na wartość logiczną int shakeCount. Ponownie wdrożyłem metodę L0AccelerationIsShaking () w Objective-C. Możesz dostosować ilość wstrząsów wymaganą przez ulepszenie ilości dodanej do shakeCount. Nie jestem pewien, czy znalazłem optymalne wartości, ale wydaje się, że jak dotąd działa dobrze. Mam nadzieję, że to pomoże komuś:
PS: Ustawiłem interwał aktualizacji na 1/15 sekundy.
źródło
Musisz sprawdzić akcelerometr za pomocą akcelerometru: didAccelerate: metoda będąca częścią protokołu UIAccelerometerDelegate i sprawdzić, czy wartości przekraczają próg dla ilości ruchu potrzebnej do wstrząśnięcia.
W akcelerometrze znajduje się przyzwoity przykładowy kod: didAccelerate: metoda na dole AppController.m w przykładzie GLPaint, który jest dostępny na stronie programisty iPhone'a.
źródło
W iOS 8.3 (być może wcześniejszym) z Swift jest to tak proste, jak zastąpienie metod
motionBegan
lubmotionEnded
w kontrolerze widoku:źródło
To jest podstawowy kod delegowany, którego potrzebujesz:
Ustaw także odpowiedni kod w interfejsie. to znaczy:
@ interfejs MyViewController: UIViewController <UIPickerViewDelegate, UIPickerViewDataSource, UIAccelerometerDelegate>
źródło
Sprawdź przykład GLPaint.
http://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html
źródło
Dodaj następujące metody w pliku ViewController.m, działa poprawnie
źródło
Przepraszam, że opublikowałem to jako odpowiedź, a nie jako komentarz, ale jak widać, jestem nowy w stosie przepełnienia stosu, więc nie jestem jeszcze wystarczająco wiarygodny, aby publikować komentarze!
Tak czy inaczej, po raz drugi @ zastanawiam się nad ustawieniem statusu pierwszego odpowiadającego, gdy widok jest częścią hierarchii widoku. Tak więc na przykład ustawienie statusu pierwszego odpowiadającego w
viewDidLoad
metodzie kontrolerów widoku nie zadziała. A jeśli nie masz pewności, czy działa,[view becomeFirstResponder]
zwraca wartość logiczną, którą możesz przetestować.Kolejny punkt: Państwo może użyć kontrolera widoku, aby uchwycić zdarzenia wstrząsnąć, jeśli nie chcesz utworzyć podklasę UIView niepotrzebnie. Wiem, że to nie tyle kłopotów, ale wciąż istnieje opcja. Po prostu przenieś fragmenty kodu, które Kendall umieścił w podklasie UIView do swojego kontrolera i wysyłaj wiadomości
becomeFirstResponder
orazresignFirstResponder
doself
podklasy UIView.źródło
Po pierwsze, wiem, że jest to stary post, ale nadal jest aktualny i stwierdziłem, że dwie najwyżej ocenione odpowiedzi nie wykryły wstrząsu tak wcześnie, jak to możliwe . Oto jak to zrobić:
W twoim ViewController:
źródło
Najłatwiejszym rozwiązaniem jest uzyskanie nowego okna głównego dla aplikacji:
Następnie w aplikacji deleguj:
Jeśli używasz Storyboard, może to być trudniejsze, nie wiem dokładnie, jaki kod będzie potrzebny w delegacie aplikacji.
źródło
@implementation
od Xcode 5.Wystarczy użyć tych trzech metod, aby to zrobić
Szczegółowe informacje można sprawdzić kompletny przykładowy kod na nie
źródło
Swiftease wersja oparta na pierwszej odpowiedzi!
źródło
Aby włączyć tę aplikację, utworzyłem kategorię w UIWindow:
źródło