OnClickListener - x, y Ort des Ereignisses?

84

Ich habe eine benutzerdefinierte Ansicht, die von Ansicht abgeleitet ist. Ich möchte benachrichtigt werden, wenn auf die Ansicht geklickt wird und die x, y-Position, an der der Klick stattgefunden hat. Gleiches gilt für lange Klicks.

Sieht so aus, ich muss es überschreiben onTouchEvent(). Gibt es jedoch keine Möglichkeit, den x, y-Ort des Ereignisses von einem OnClickListenerzu erhalten?

Wenn nicht, wie lässt sich dann gut feststellen, ob ein Bewegungsereignis ein "echter" Klick oder ein langer Klick usw. ist? Das onTouchEventerzeugt viele Ereignisse in schneller Folge usw.

Kennzeichen
quelle

Antworten:

90

Danke dir. Genau das habe ich gesucht. Mein Code lautet jetzt:

imageView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN){
                textView.setText("Touch coordinates : " +
                        String.valueOf(event.getX()) + "x" + String.valueOf(event.getY()));
            }
            return true;
        }
    });

was genau das tut, wonach Mark gefragt hat ...

Vering
quelle
4
Sind diese Koordinaten lokal für die Ansicht?
Nigel
7
Sollte der onTouch-Handler nicht zurückkehren, falsedamit Berührungsereignisse nicht blockiert werden? (View.OnTouchListener.onTouch gibt true zurück, wenn der Listener das Ereignis konsumiert hat, andernfalls false.)
ehartwell
5
Nun, nicht "genau" das, da da OnClickListenerausgelöst wird, wenn der Finger losgelassen wird, also ACTION_UPmit Einschränkungen: Wenn eine fliegende (Wisch-) Geste ausgeführt wurde, OnClickListenerwird sie nicht ausgelöst, sondern ACTION_UPwird weiterhin verarbeitet.
Alex Semeniuk
Ich versuche, Text auf die angeklickten Koordinaten zu schreiben. Ich habe versucht, Text an Koordinaten (event.getX(), event.getY()) zu schreiben, aber er schreibt nicht an der richtigen Position.
Prinz
Hier ist meine Frage: stackoverflow.com/questions/40199539/…
Prince
26

Vollständiges Beispiel

Den anderen Antworten fehlen einige Details. Hier ist ein vollständiges Beispiel.

public class MainActivity extends AppCompatActivity {

    // class member variable to save the X,Y coordinates
    private float[] lastTouchDownXY = new float[2];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // add both a touch listener and a click listener
        View myView = findViewById(R.id.my_view);
        myView.setOnTouchListener(touchListener);
        myView.setOnClickListener(clickListener);
    }

    // the purpose of the touch listener is just to store the touch X,Y coordinates
    View.OnTouchListener touchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            // save the X,Y coordinates
            if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
                lastTouchDownXY[0] = event.getX();
                lastTouchDownXY[1] = event.getY();
            }

            // let the touch event pass on to whoever needs it
            return false;
        }
    };

    View.OnClickListener clickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // retrieve the stored coordinates
            float x = lastTouchDownXY[0];
            float y = lastTouchDownXY[1];

            // use the coordinates for whatever
            Log.i("TAG", "onLongClick: x = " + x + ", y = " + y);
        }
    };
}

Zusammenfassung

  • Fügen Sie eine Klassenvariable hinzu, um die Koordinaten zu speichern
  • Speichern Sie die X-, Y-Koordinaten mit einem OnTouchListener
  • Greifen Sie auf die X-, Y-Koordinaten in der zu OnClickListener
Suragch
quelle
1
Anstelle eines Float-Arrays mit 2 Leerzeichen könnte ein Point () verwendet werden.
ZooMagic
Punkt hat X und Y vom Typ Ganzzahl. Die Koordinaten sind Gleitkommawerte. Wenn ich die Point-Klasse verwende, denke ich, dass ich an Präzision verlieren werde. Ich bin sehr neu in Android und habe möglicherweise etwas verpasst.
Mboada
@mboada, du hast recht. PointF wäre besser.
Suragch
Es sollte eine Möglichkeit geben, onTouchListener zu vermeiden und nur onClickListener zu verwenden. ContextMenu braucht es irgendwie nicht. Wenn Sie auf ein Element klicken und das Menü mit der Ansicht als Anker anzeigen, weiß es, wo es in der Nähe der Berührungsposition platziert werden muss. Siehe hier: stackoverflow.com/q/57290574/878126 . Weißt du wie es möglich ist? Wenn ja, antworten Sie bitte dort.
Android-Entwickler
3

OnTouchEvent überschreiben (MotionEvent ev)

Dann können Sie tun:

ev.getXLocation()

Oder etwas ähnliches. Haben Sie eine Butches.

An Herrn
quelle
2
Hallo Tom, ja, wir können onTouchEvent verwenden, aber dann müssen wir selbst zwischen Klicks und langen Klicks unterscheiden, nicht wahr? Es macht keinen Sinn, dass sie Ihnen keine Möglichkeit bieten, zu wissen, wo der Klick oder der lange Klick in OnClickListener usw. stattgefunden hat. Danke
Mark
21
Sie müssen lediglich die x & y-Position des letzten ACTION_UP- oder ACTION_MOVE-Ereignisses aufzeichnen und diese Werte in Ihrem OnClickListener verwenden.
Romain Guy
@RomainGuy Sie müssen jedoch auch den Abstand zwischen den beiden Punkten berechnen, um einen Klick zu bestimmen. Wenn Sie das Ereignis ACTION_DOWN bei (0,0) und das Ereignis ACTION_UP bei (100.100) erhalten, ist dies definitiv kein Klick.
TheRealChx101
@ chx101, was RomainGuy meinte (glaube ich) war, dass wenn Sie nur auf touchevent die letzten action_up-Koordinaten aufzeichnen, dies die Koordinaten sind, die Sie in onclick verwenden können. Ich denke jedoch, dass dies in der Praxis eine Unterklasse der Ansicht erfordern würde, oder der Onclick wird nicht aufgerufen. Sie können den Wasserhahn auch als Gestenmelder erkennen, wie in stackoverflow.com/questions/19538747/… Antwort
Lassi Kinnunen
0

Sie können eine Erweiterungsfunktion in Kotlin wie folgt erstellen:

fun View.setOnClickListenerWithPoint(action: (Point) -> Unit) {
    val coordinates = Point()
    val screenPosition = IntArray(2)
    setOnTouchListener { v, event ->
        if (event.action == MotionEvent.ACTION_DOWN) {
            v.getLocationOnScreen(screenPosition)
            coordinates.set(event.x.toInt() + screenPosition[0], event.y.toInt() + screenPosition[1])
        }
        false
    }
    setOnClickListener {
        action.invoke(coordinates)
    }
}

Wenn Sie einen langen Klick benötigen, ersetzen Sie ihn einfach setOnClickListener

Ich verwende, getLocationOnScreen()weil ich Koordinaten für den ViewHolder von RecyclerView benötige

Vitalii Malyi
quelle