Chcę uzyskać fling
wykrywanie gestów w mojej aplikacji na Androida.
Mam to, GridLayout
co zawiera 9 ImageView
s. Źródło można znaleźć tutaj: Układ siatki Romaina Guysa .
Plik, który biorę pochodzi od Romaina Guy'a aplikacji Photostream i został tylko nieznacznie dostosowany.
W przypadku prostego kliknięcia muszę tylko ustawić onClickListener
dla każdego ImageView
dodawanego jako główny, activity
który implementuje View.OnClickListener
. Nieskończenie bardziej skomplikowane wydaje się wdrożenie czegoś, co rozpoznaje fling
. Zakładam, że dzieje się tak, ponieważ może się rozciągaćviews
?
Jeśli moja aktywność się implementuje
OnGestureListener
, nie wiem, jak ustawić to jako detektor gestów dla dodawanych widokówGrid
lubImage
.public class SelectFilterActivity extends Activity implements View.OnClickListener, OnGestureListener { ...
Jeśli moja aktywność się implementuje,
OnTouchListener
to nie mamonFling
metodyoverride
(ma dwa zdarzenia jako parametry pozwalające mi ustalić, czy rzutowanie było warte uwagi).public class SelectFilterActivity extends Activity implements View.OnClickListener, OnTouchListener { ...
Jeśli zrobię niestandardowy
View
,GestureImageView
to rozszerzaImageView
nie wiem, jak powiedzieć aktywności, żefling
wystąpił z widoku. W każdym razie próbowałem tego i metody nie były wywoływane, kiedy dotknąłem ekranu.
Naprawdę potrzebuję konkretnego przykładu tego działania w różnych widokach. Co, kiedy i jak mam to załączyć listener
? Muszę też być w stanie wykryć pojedyncze kliknięcia.
// Gesture detection
mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
int dx = (int) (e2.getX() - e1.getX());
// don't accept the fling if it's too short
// as it may conflict with a button push
if (Math.abs(dx) > MAJOR_MOVE && Math.abs(velocityX) > Math.absvelocityY)) {
if (velocityX > 0) {
moveRight();
} else {
moveLeft();
}
return true;
} else {
return false;
}
}
});
Czy można umieścić przezroczysty widok na górze ekranu, aby uchwycić rzuty?
Jeśli zdecyduję się nie wyświetlać inflate
podrzędnych widoków obrazów z XML, czy mogę przekazać GestureDetector
parametr konstruktora do nowej podklasy ImageView
, którą tworzę?
Jest to bardzo prosta czynność, dla której próbuję uruchomić fling
wykrywanie: SelectFilterActivity (na podstawie strumienia zdjęć) .
Patrzyłem na te źródła:
Do tej pory nic mi nie działało i liczyłem na pewne wskazówki.
Odpowiedzi:
Dzięki Code Shogun , którego kod dostosowałem do mojej sytuacji.
Pozwól, aby Twoje działanie było realizowane
OnClickListener
jak zwykle:Dołącz detektor gestów do wszystkich widoków dodawanych do głównego układu;
Z podziwem obserwuj, jak uderzają twoje przesłonięte metody, zarówno
onClick(View v)
aktywność, jak ionFling
detektor gestów.Taniec po „rzucaniu” jest opcjonalny, ale zachęcany.
źródło
Jedna z powyższych odpowiedzi wspomina obsługę różnych gęstości pikseli, ale sugeruje ręczne obliczenie parametrów przeciągnięcia. Warto zauważyć, że faktycznie można uzyskać skalowane, rozsądne wartości z systemu za pomocą
ViewConfiguration
klasy:Zauważyłem, że użycie tych wartości powoduje, że „odczucie” rzutu jest bardziej spójne między aplikacją a resztą systemu.
źródło
swipeMinDistance = vc.getScaledPagingTouchSlop()
iswipeMaxOffPath = vc.getScaledTouchSlop()
.getScaledTouchSlop
niezręcznie daje mi bardzo niewielki wynik kompensacji. Na przykład tylko 24 piksele na ekranie o wysokości 540, bardzo trudno jest trzymać go w zasięgu palcem. : SRobię to trochę inaczej i napisałem dodatkową klasę detektora, która implementuje
View.onTouchListener
onCreate
po prostu dodaj go do najniższego układu takiego jak ten:gdzie id.lowestLayout to id.xxx dla widoku najniższego w hierarchii układu, a najniższy układ jest zadeklarowany jako układ względny
A potem jest faktyczna klasa detektora przesunięcia aktywności:
Działa naprawdę dobrze dla mnie!
źródło
Lekko zmodyfikowałem i naprawiłem rozwiązanie Thomasa Fankhausera
Cały system składa się z dwóch plików: SwipeInterface i ActivitySwipeDetector
SwipeInterface.java
Detektor
jest używany w następujący sposób:
I podczas implementacji
Activity
musisz zaimplementować metody z SwipeInterface , i możesz dowiedzieć się, na którym wywołano zdarzenie View Swipe .źródło
v.performClick();
, który jest używany do nieużywania zdarzenia do OnClickListener, jeśli jest ustawiony w tym samym widokuPowyższy kod detektora gestów przesuwania jest bardzo przydatny! Możesz jednak chcieć sprawić, by gęstość tego rozwiązania była agnostyczna, używając następujących wartości względnych
(REL_SWIPE)
zamiast wartości bezwzględnych(SWIPE_)
źródło
Moja wersja rozwiązania zaproponowana przez Thomasa Fankhausera i Marka Seberę (nie obsługuje przeciągnięć pionowych):
SwipeInterface.java
ActivitySwipeDetector.java
źródło
To pytanie jest trochę stare i w lipcu 2011 r. Google wydało Pakiet zgodności, wersja 3), który obejmuje wersję
ViewPager
zgodną z systemem Android 1.6 w górę. WGestureListener
odpowiedzi na to pytanie wysłane nie czują się bardzo elegancko na Androida. Jeśli szukasz kodu używanego do przełączania zdjęć w Galerii Androida lub przełączania widoków w nowej aplikacji Play Market, to na pewnoViewPager
.Oto kilka linków, aby uzyskać więcej informacji:
źródło
Istnieje wbudowany interfejs, którego można używać bezpośrednio do wszystkich gestów:
Oto wyjaśnienie dla użytkownika na poziomie podstawowym: Istnieją 2 rodzaje importu, zachowaj ostrożność przy wyborze, że oba są różne
źródło
W Internecie (i na tej stronie) jest kilka propozycji użycia ViewConfiguration. getScaledTouchSlop (), aby mieć wartość skalowaną dla urządzenia
SWIPE_MIN_DISTANCE
.getScaledTouchSlop()
jest przeznaczony do „ przewijania odległości „progu ”, a nie przesuwania. Odległość progu przewijania musi być mniejsza niż odległość progowa „przechodzenia między stronami”. Na przykład ta funkcja zwraca 12 pikseli na moim telefonie Samsung GS2, a przykłady podane na tej stronie mają około 100 pikseli.Z API poziomu 8 (Android 2.2, Froyo), masz
getScaledPagingTouchSlop()
, przeznaczony do przesuwania strony. Na moim urządzeniu zwraca 24 (piksele). Więc jeśli jesteś na poziomie API <8, myślę, że „2 *getScaledTouchSlop()
” powinno być „standardowym” progiem przeciągnięcia. Ale użytkownicy mojej aplikacji z małymi ekranami powiedzieli mi, że jest jej za mało ... Podobnie jak w mojej aplikacji, możesz przewijać w pionie i zmieniać stronę w poziomie. Przy proponowanej wartości czasami zmieniają stronę zamiast przewijania.źródło
Również jako niewielkie ulepszenie.
Głównym powodem bloku try / catch jest to, że e1 może być zerowy dla początkowego ruchu. oprócz try / catch dołącz test na zero i return. podobne do następujących
źródło
Jest tu wiele doskonałych informacji. Niestety, wiele z tego kodu przetwarzania rozproszonego jest rozrzuconych po różnych witrynach w różnych stanach ukończenia, chociaż można by pomyśleć, że jest to niezbędne w wielu aplikacjach.
Poświęciłem czas na stworzenie flingera, który sprawdza, czy spełnione są odpowiednie warunki. Dodałem detektor rzutowania stron, który dodaje więcej kontroli, aby upewnić się, że rzuty spełniają próg dla rzutów stron. Oba te nasłuchiwania umożliwiają łatwe ograniczenie rzutów do osi poziomej lub pionowej. Możesz zobaczyć, jak jest używany w widoku do przesuwania obrazów . Przyznaję, że ludzie tutaj przeprowadzili większość badań --- właśnie połączyłem to w użyteczną bibliotekę.
Ostatnie kilka dni to mój pierwszy kłopot z kodowaniem na Androidzie; oczekuj znacznie więcej .
źródło
Jest to połączona odpowiedź dwóch odpowiedzi u góry, jeśli ktoś chce działającej implementacji.
źródło
absDeltaY > minSwipeDelta
,absVelocityY > minSwipeVelocity
,absVelocityY < maxSwipeVelocity
tylko w przypadku, gdyminSwipeDelta
! =getScaledTouchSlop
,minSwipeVelocity
! =getScaledMinimumFlingVelocity
,maxSwipeVelocity
! =getScaledMaximumFlingVelocity
, Czyli sprawdzić tylko wtedy, gdy te tak zwane „default” (mam na myśli getScaledTouchSlop, getScaledMinimumFlingVelocity, getScaledMaximumFlingVelocity) wartości są skalowane lub zmieniane według Państwa własne życzenie.ACTION_UP
, nieACTION_MOVE
lubACTION_POINTER_UP
, tj. Tylko jako wynik w pełni zrealizowanego gestu). (Nie sprawdziłem innych wersji API, więc komentarze są mile widziane).Możesz użyć biblioteki droidQuery do obsługi rzutów , kliknięć, długich kliknięć i zdarzeń niestandardowych. Implementacja jest oparta na mojej poprzedniej odpowiedzi poniżej, ale droidQuery zapewnia płynną , prostą składnię:
Oryginalna odpowiedź
Ta odpowiedź wykorzystuje kombinację składników z innych odpowiedzi tutaj. Składa się z
SwipeDetector
klasy, która ma wewnętrzny interfejs do nasłuchiwania zdarzeń. Podaję również,RelativeLayout
aby pokazać, jak zastąpićView
aonTouch
metody, aby umożliwić zarówno wydarzenia machnięcia i inne imprezy wykrywane (takie jak kliknięcia lub długich kliknięć).SwipeDetector
Przesuń widok przechwytywacza
źródło
SwipeInterceptorView
, więc jego kliknięcie jest obsługiwane jako pierwsze. Możesz to naprawić, wdrażając własny mechanizm klikania, implementująconTouchListener
lub, jako obejście problemu, możesz słuchać długich kliknięć zamiast kliknięć (patrzView.setOnLongClickListener
).Wiem, że jest za późno, aby odpowiedzieć, ale wciąż wysyłam wykrywanie machnięcia dla ListView , jak używać Swipe Touch Listener w elemencie ListView .
Refrence: Exterminator13 (jedna z odpowiedzi na tej stronie)
Utwórz jeden ActivitySwipeDetector.class
Nazwij to ze swojej klasy aktywności w ten sposób:
I nie zapomnij wdrożyć SwipeInterface, który da ci dwie metody @override:
źródło
MAX_OFF_PATH = 5 * vc.getScaledPagingTouchSlop()
jest wygodniejsze dla przesunięcia kciuka, naturalnie podróżującego po lekkim łuku.Gesty to te subtelne ruchy, które uruchamiają interakcje między ekranem dotykowym a użytkownikiem. Trwa od pierwszego dotknięcia ekranu do momentu, gdy ostatni palec opuści powierzchnię.
Android zapewnia nam klasę o nazwie GestureDetector, za pomocą której możemy wykrywać typowe gesty, takie jak stukanie w dół i w górę, przeciąganie w pionie i poziomie (fling), długie i krótkie naciśnięcie, podwójne stuknięcia itp . i dołącz do nich słuchaczy.
Spraw, by nasza klasa Activity zaimplementowała interfejsy GestureDetector.OnDoubleTapListener (do wykrywania gestów dwukrotnego dotknięcia) i GestureDetector.OnGestureListener i zaimplementuje wszystkie metody abstrakcyjne. Więcej informacji. możesz odwiedzić https://developer.android.com/training/gestures/detector.html . Kurtuazja
Do testu demonstracyjnego. GestureDetectorDemo
źródło
Jeśli nie chcesz tworzyć osobnej klasy lub tworzyć kodu złożonego,
możesz po prostu utworzyć zmienną GestureDetector w OnTouchListener i ułatwić sobie kod
namVyuVar może być dowolną nazwą Widoku, w której musisz ustawić listę
źródło
Wszystkim: nie zapomnij o przypadku MotionEvent.ACTION_CANCEL:
wywołuje 30% machnięcia bez ACTION_UP
i jest w tym przypadku równa ACTION_UP
źródło
Potrzebowałem bardziej ogólnej klasy, wziąłem klasę Tomasa i dodałem interfejs, który wysyła zdarzenia do twojej aktywności lub fragmentu. zarejestruje on detektor w konstruktorze, więc upewnij się, że implementujesz interfejs, w przeciwnym razie zostanie przekroczony ClassCastException. interfejs zwraca jedną z czterech końcowych wartości int zdefiniowanych w klasie i zwróci widok, na którym został aktywowany.
źródło