Ich möchte, dass meine App erkennt, wenn ein Benutzer auf dem Telefonbildschirm von rechts nach links wischt.
Wie macht man das?
endryha
Ich möchte, dass meine App erkennt, wenn ein Benutzer auf dem Telefonbildschirm von rechts nach links wischt.
Wie macht man das?
Mirek Russin
OnSwipeTouchListener.java:
import android.content.Context;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener (Context ctx){
gestureDetector = new GestureDetector(ctx, new GestureListener());
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
result = true;
}
}
else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom();
} else {
onSwipeTop();
}
result = true;
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeTop() {
}
public void onSwipeBottom() {
}
}
Verwendungszweck:
imageView.setOnTouchListener(new OnSwipeTouchListener(MyActivity.this) {
public void onSwipeTop() {
Toast.makeText(MyActivity.this, "top", Toast.LENGTH_SHORT).show();
}
public void onSwipeRight() {
Toast.makeText(MyActivity.this, "right", Toast.LENGTH_SHORT).show();
}
public void onSwipeLeft() {
Toast.makeText(MyActivity.this, "left", Toast.LENGTH_SHORT).show();
}
public void onSwipeBottom() {
Toast.makeText(MyActivity.this, "bottom", Toast.LENGTH_SHORT).show();
}
});
funktioniert super, aber super.onTouch(view, motionEvent); gibt mir eine Fehlermeldung in Eclipse “ist für den Typ Objekt nicht definiert”. Das löschen funktioniert super.
– Opiatefuchs
22. Juni 2013 um 17:47 Uhr
Danke funktioniert wie ein Zauber, aber Sie sollten einen Konstruktor hinzufügen OnSwipeTouchListener
das erhält einen Kontext, weil dieser Konstruktor von GestureDetector
ist seit API-Ebene 3 veraltet und instanziiert die GestureDetector
in diesem Konstruktor.
– Hugo Alves
1. Oktober 2013 um 9:56 Uhr
danke, es hat bei mir mit diesen Modifikationen funktioniert: stackoverflow.com/a/19506010/401403
– Arash
4. April 2014 um 10:35 Uhr
aber “onDown” wird nie aufgerufen. Infolgedessen ist mein e1 immer null und ich kann nichts dagegen tun.
– Mangusta
30. Mai 2014 um 7:04 Uhr
Meine Lösung für diese Antwort ist, sich zu bewegen onTouch
in die OnSwipeTouchListener
andernfalls zeigt meine IDE den Fehler “Zugriff auf privates Mitglied” an
– GeRong
20. Dezember 2014 um 12:46 Uhr
Dieser Code erkennt Wischbewegungen nach links und rechts, vermeidet veraltete API-Aufrufe und weist andere verschiedene Verbesserungen gegenüber früheren Antworten auf.
/**
* Detects left and right swipes across a view.
*/
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener(Context context) {
gestureDetector = new GestureDetector(context, new GestureListener());
}
public void onSwipeLeft() {
}
public void onSwipeRight() {
}
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_DISTANCE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float distanceX = e2.getX() - e1.getX();
float distanceY = e2.getY() - e1.getY();
if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (distanceX > 0)
onSwipeRight();
else
onSwipeLeft();
return true;
}
return false;
}
}
}
Verwenden Sie es wie folgt:
view.setOnTouchListener(new OnSwipeTouchListener(context) {
@Override
public void onSwipeLeft() {
// Whatever
}
});
@Jona Sie sollten sich auf jeden Fall ein gutes Buch oder eine andere Ressource zu Android-Grundlagen besorgen; andernfalls wird es frustrierend sein, Lösungen aus StackOverflow zusammenzuschustern. Eine gute Option ist die offizielle Training für Android-Entwickler. Die Sektion Starten einer Aktivität erzählt darüber, wo Sie setzen würden setOnTouchListener
(normalerweise im onCreate
). context
ist der this
Zeiger (es sei denn, Sie erstellen ein Fragment).
– Eduard Brey
20. Juni 2014 um 10:14 Uhr
@ Lara, ich habe das nicht versucht, aber Sie könnten versuchen, es zu überschreiben SimpleOnGestureListener.onSingleTapConfirmed.
– Eduard Brey
3. Juli 2014 um 12:44 Uhr
Danke, Eduard. Ich habe auch festgestellt, dass es ausreicht, die Rückgabe von onDown von true auf false zu ändern.
– Lara
3. Juli 2014 um 21:08 Uhr
@Signo, die Aktivität, die die Ansicht enthält, stellt den Kontext bereit. Verwenden Sie im allgemeinen Fall des Hinzufügens der Ansicht zu einem Fragment Fragment.getActivity()
.
– Eduard Brey
1. Dezember 2014 um 19:31 Uhr
@coderVishal Abhängig von Ihrem Zweck können Sie nützlich sein SwipeRefreshLayoutder SwipeRefreshLayoutBasic Beispiel oder eine seiner Varianten.
– Eduard Brey
8. März 2015 um 12:20 Uhr
ruX
Wenn Sie auch Klickereignisse verarbeiten müssen, hier einige Änderungen:
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector = new GestureDetector(new GestureListener());
public boolean onTouch(final View v, final MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
result = onSwipeRight();
} else {
result = onSwipeLeft();
}
}
} else {
if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
result = onSwipeBottom();
} else {
result = onSwipeTop();
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public boolean onSwipeRight() {
return false;
}
public boolean onSwipeLeft() {
return false;
}
public boolean onSwipeTop() {
return false;
}
public boolean onSwipeBottom() {
return false;
}
}
Und Beispielverwendung:
background.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
toggleSomething();
}
});
background.setOnTouchListener(new OnSwipeTouchListener() {
public boolean onSwipeTop() {
Toast.makeText(MainActivity.this, "top", Toast.LENGTH_SHORT).show();
return true;
}
public boolean onSwipeRight() {
Toast.makeText(MainActivity.this, "right", Toast.LENGTH_SHORT).show();
return true;
}
public boolean onSwipeLeft() {
Toast.makeText(MainActivity.this, "left", Toast.LENGTH_SHORT).show();
return true;
}
public boolean onSwipeBottom() {
Toast.makeText(MainActivity.this, "bottom", Toast.LENGTH_SHORT).show();
return true;
}
});
Ich sehe die Änderungen in Ihrem modifizierten OnSwipeTouchListener nicht so einfach. Wo ist es genau ?
– Nikolaus Zozol
23. Oktober 2013 um 20:48 Uhr
Dies sollte die akzeptierte Antwort sein … Unterschiede sind subtil, aber sehr wichtig. Erstens gibt es kein onDown(). Zweitens geben die Handler einen booleschen Wert zurück, um zu signalisieren, ob sie das Ereignis verarbeitet haben oder nicht. Dies ist von größter Bedeutung, wenn Sie mehr als nur einen Handler für dieselbe Ansicht benötigen (was sowieso der Standardfall sein sollte).
– Gabor
7. November 2014 um 23:24 Uhr
Was ist diese toggleSomething() Methode?
– Tung
1. Februar 2015 um 8:57 Uhr
@tung nur ein normaler Tap-Handler (keine Geste).
– ruX
2. Februar 2015 um 15:35 Uhr
@NicolasZozol Java-Code-Stil, alle Wischrichtungen, Klick-Handler
– ruX
2. Februar 2015 um 15:38 Uhr
agunal
Erweiterung von Mireks Antwort für den Fall, dass Sie die Wischgesten in einer Bildlaufansicht verwenden möchten. Standardmäßig wird der Touch-Listener für die Scroll-Ansicht deaktiviert und daher findet keine Scroll-Aktion statt. Um dies zu beheben, müssen Sie die überschreiben dispatchTouchEvent
Methode der Activity
und geben Sie die geerbte Version dieser Methode zurück, nachdem Sie mit Ihrem eigenen Listener fertig sind.
Um ein paar Änderungen an Mireks Code vorzunehmen: Ich füge einen Getter für die hinzu gestureDetector
in dem OnSwipeTouchListener
.
public GestureDetector getGestureDetector(){
return gestureDetector;
}
Deklarieren Sie die OnSwipeTouchListener
innerhalb der Aktivität als klassenweites Feld.
OnSwipeTouchListener onSwipeTouchListener;
Ändern Sie den Verwendungscode entsprechend:
onSwipeTouchListener = new OnSwipeTouchListener(MyActivity.this) {
public void onSwipeTop() {
Toast.makeText(MyActivity.this, "top", Toast.LENGTH_SHORT).show();
}
public void onSwipeRight() {
Toast.makeText(MyActivity.this, "right", Toast.LENGTH_SHORT).show();
}
public void onSwipeLeft() {
Toast.makeText(MyActivity.this, "left", Toast.LENGTH_SHORT).show();
}
public void onSwipeBottom() {
Toast.makeText(MyActivity.this, "bottom", Toast.LENGTH_SHORT).show();
}
});
imageView.setOnTouchListener(onSwipeTouchListener);
Und überschreibe die dispatchTouchEvent
Methode drinnen Activity
:
@Override
public boolean dispatchTouchEvent(MotionEvent ev){
swipeListener.getGestureDetector().onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
Jetzt sollten sowohl Scroll- als auch Wischaktionen funktionieren.
Um zu haben Click Listener
, DoubleClick Listener
, OnLongPress Listener
, Swipe Left
, Swipe Right
, Swipe Up
, Swipe Down
auf Single View
du musst setOnTouchListener
. dh,
view.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this) {
@Override
public void onClick() {
super.onClick();
// your on click here
}
@Override
public void onDoubleClick() {
super.onDoubleClick();
// your on onDoubleClick here
}
@Override
public void onLongClick() {
super.onLongClick();
// your on onLongClick here
}
@Override
public void onSwipeUp() {
super.onSwipeUp();
// your swipe up here
}
@Override
public void onSwipeDown() {
super.onSwipeDown();
// your swipe down here.
}
@Override
public void onSwipeLeft() {
super.onSwipeLeft();
// your swipe left here.
}
@Override
public void onSwipeRight() {
super.onSwipeRight();
// your swipe right here.
}
});
}
Dazu benötigen Sie OnSwipeTouchListener
Klasse, die implementiert OnTouchListener
.
public class OnSwipeTouchListener implements View.OnTouchListener {
private GestureDetector gestureDetector;
public OnSwipeTouchListener(Context c) {
gestureDetector = new GestureDetector(c, new GestureListener());
}
public boolean onTouch(final View view, final MotionEvent motionEvent) {
return gestureDetector.onTouchEvent(motionEvent);
}
private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
onClick();
return super.onSingleTapUp(e);
}
@Override
public boolean onDoubleTap(MotionEvent e) {
onDoubleClick();
return super.onDoubleTap(e);
}
@Override
public void onLongPress(MotionEvent e) {
onLongClick();
super.onLongPress(e);
}
// Determines the fling velocity and then fires the appropriate swipe event accordingly
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
}
} else {
if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeDown();
} else {
onSwipeUp();
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeUp() {
}
public void onSwipeDown() {
}
public void onClick() {
}
public void onDoubleClick() {
}
public void onLongClick() {
}
}
Zalas Lösung ist einfach und klar und hat mir bei Wischaktionen in Android sehr geholfen. Diese Lösung löst Anfänger, die Probleme mit Wischgesten haben.
– Jennifer
2. September 2015 um 15:34 Uhr
@Jaydipsinh Zala, du sparst mir Zeit, unglaublich. Dies wird mein Problem der Anzeige des Scrollens oben und unten beim Scrollen lösen.
– TejaDroid
10. Mai 2016 um 10:12 Uhr
Das nenne ich eine vollständige Antwort. Als ich die Swipes hinzufügte, verlor ich meine Klickeigenschaften, daher musste ich die onClick-Methode wie in dieser Antwort überschreiben. Danke Kerl!
– Bald Santos
28. Juli 2018 um 13:52 Uhr
@Jaydipsinh Zala Ich bin mir nicht sicher, was ich falsch mache. Wenn ich den OnSwipeTouchListener zu meiner WebView hinzufüge, wird die Interaktion mit der Website in WebView entfernt. Kannst du mir bitte helfen?
– AL̲̳I
16. März 2020 um 10:23 Uhr
MHS Fisher
Die Kotlin-Version von @Mirek Rusin ist hier:
OnSwipeTouchListener.kt :
open class OnSwipeTouchListener(ctx: Context) : OnTouchListener {
private val gestureDetector: GestureDetector
companion object {
private val SWIPE_THRESHOLD = 100
private val SWIPE_VELOCITY_THRESHOLD = 100
}
init {
gestureDetector = GestureDetector(ctx, GestureListener())
}
override fun onTouch(v: View, event: MotionEvent): Boolean {
return gestureDetector.onTouchEvent(event)
}
private inner class GestureListener : SimpleOnGestureListener() {
override fun onDown(e: MotionEvent): Boolean {
return true
}
override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
var result = false
try {
val diffY = e2.y - e1.y
val diffX = e2.x - e1.x
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight()
} else {
onSwipeLeft()
}
result = true
}
} else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom()
} else {
onSwipeTop()
}
result = true
}
} catch (exception: Exception) {
exception.printStackTrace()
}
return result
}
}
open fun onSwipeRight() {}
open fun onSwipeLeft() {}
open fun onSwipeTop() {}
open fun onSwipeBottom() {}
}
Verwendungszweck:
view.setOnTouchListener(object : OnSwipeTouchListener(context) {
override fun onSwipeTop() {
super.onSwipeTop()
}
override fun onSwipeBottom() {
super.onSwipeBottom()
}
override fun onSwipeLeft() {
super.onSwipeLeft()
}
override fun onSwipeRight() {
super.onSwipeRight()
}
})
der open
Stichwort war für mich der Punkt…
Zalas Lösung ist einfach und klar und hat mir bei Wischaktionen in Android sehr geholfen. Diese Lösung löst Anfänger, die Probleme mit Wischgesten haben.
– Jennifer
2. September 2015 um 15:34 Uhr
@Jaydipsinh Zala, du sparst mir Zeit, unglaublich. Dies wird mein Problem der Anzeige des Scrollens oben und unten beim Scrollen lösen.
– TejaDroid
10. Mai 2016 um 10:12 Uhr
Das nenne ich eine vollständige Antwort. Als ich die Swipes hinzufügte, verlor ich meine Klickeigenschaften, daher musste ich die onClick-Methode wie in dieser Antwort überschreiben. Danke Kerl!
– Bald Santos
28. Juli 2018 um 13:52 Uhr
@Jaydipsinh Zala Ich bin mir nicht sicher, was ich falsch mache. Wenn ich den OnSwipeTouchListener zu meiner WebView hinzufüge, wird die Interaktion mit der Website in WebView entfernt. Kannst du mir bitte helfen?
– AL̲̳I
16. März 2020 um 10:23 Uhr
Sie brauchen keine komplizierten Berechnungen. Dies kann nur durch die Verwendung erfolgen OnGestureListener
Schnittstelle ab GestureDetector
Klasse.
Innen onFling
Methode können Sie alle vier Richtungen wie folgt erkennen:
MyGestureListener.java
:
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
public class MyGestureListener implements GestureDetector.OnGestureListener{
private static final long VELOCITY_THRESHOLD = 3000;
@Override
public boolean onDown(final MotionEvent e){ return false; }
@Override
public void onShowPress(final MotionEvent e){ }
@Override
public boolean onSingleTapUp(final MotionEvent e){ return false; }
@Override
public boolean onScroll(final MotionEvent e1, final MotionEvent e2, final float distanceX,
final float distanceY){ return false; }
@Override
public void onLongPress(final MotionEvent e){ }
@Override
public boolean onFling(final MotionEvent e1, final MotionEvent e2,
final float velocityX,
final float velocityY){
if(Math.abs(velocityX) < VELOCITY_THRESHOLD
&& Math.abs(velocityY) < VELOCITY_THRESHOLD){
return false;//if the fling is not fast enough then it's just like drag
}
//if velocity in X direction is higher than velocity in Y direction,
//then the fling is horizontal, else->vertical
if(Math.abs(velocityX) > Math.abs(velocityY)){
if(velocityX >= 0){
Log.i("TAG", "swipe right");
}else{//if velocityX is negative, then it's towards left
Log.i("TAG", "swipe left");
}
}else{
if(velocityY >= 0){
Log.i("TAG", "swipe down");
}else{
Log.i("TAG", "swipe up");
}
}
return true;
}
}
Verwendungszweck:
GestureDetector mDetector = new GestureDetector(MainActivity.this, new MyGestureListener());
view.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(final View v, final MotionEvent event){
return mDetector.onTouchEvent(event);
}
});
Ich habe den ganzen Müll hier durchgesehen, Sie haben Recht, keine Notwendigkeit, die Dinge zu verkomplizieren – dieser funktioniert perfekt
– Sternenwelle
10. Februar 2019 um 14:56 Uhr
Sollte VELOCITY_THRESHOLD nicht von der Bildschirmdichte abhängig sein?
– Gerrit Beuze
12. November 2019 um 10:06 Uhr
@GerritBeuze Nein, das übernimmt das Android-System. Es sendet die richtigen Werte durch velocityX
und velocityY
in onFling
Methode. Sie können zwar experimentieren, um zu sehen, welcher Wert Ihren Anforderungen am besten entspricht, aber die endgültige Zahl wäre universell.
– MDP
12. November 2019 um 22:17 Uhr
Die Antworten hier setzen das Gegenteil voraus: Sie sind nicht skaliert? : stackoverflow.com/questions/18812479/…
– Gerrit Beuze
13. November 2019 um 14:02 Uhr
@GerritBeuze Das liegt daran, dass sie selbst manuell rechnen, indem sie die Anzahl der Pixel berechnen, die der Finger zurückgelegt hat, und das ist falsch, weil es von der Pixeldichte abhängt. Sie sollten nur die Geschwindigkeit verwenden, wie ich es getan habe, die Geschwindigkeit ist fast dpi-unabhängig.
– MDP
14. November 2019 um 16:11 Uhr
Überprüfen Sie diesen Link stackoverflow.com/questions/937313/…
– Famarri
9. November 2010 um 22:23 Uhr
Siehe meine Antwort zum Wischen nach oben/unten/links/rechts stackoverflow.com/questions/13095494/…
– fernandohur
30. Juni 2015 um 23:01 Uhr
Überprüfen Sie meine Bibliothek, die hilfreich sein könnte github.com/UdiOshi85/libSwipes
– Udi Oschi
2. April 2017 um 7:39 Uhr
Überprüfen Sie die akzeptierte Antwort in Kotlin hier: stackoverflow.com/a/53791260/2201814
– MHSFisher
13. Februar 2019 um 6:59 Uhr