OnClickListener - x, y luogo dell'evento?


85

Ho una visualizzazione personalizzata derivata da View. Vorrei essere avvisato quando si fa clic sulla visualizzazione e la posizione x, y del punto in cui è avvenuto il clic. Lo stesso per i clic lunghi.

Sembra che lo faccia, devo eseguire l'override onTouchEvent(). OnClickListenerTuttavia, non c'è modo di ottenere la x, y posizione dell'evento da un ?

In caso contrario, qual è un buon modo per sapere se un evento di movimento è un clic "reale" rispetto a un clic lungo, ecc.? Il onTouchEventgenera molti eventi in rapida successione ecc.

Risposte:


92

Grazie. Era esattamente quello che stavo cercando. Il mio codice ora è:

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;
        }
    });

che fa esattamente quello che Mark ha chiesto ...


4
Queste coordinate sono locali alla vista?
Nigel

7
Il gestore onTouch non dovrebbe tornare in falsemodo da non bloccare gli eventi di tocco? (View.OnTouchListener.onTouch restituisce true se l'ascoltatore ha consumato l'evento, altrimenti false.)
ehartwell

5
Beh, non "precisamente" questo dato che OnClickListenerviene sparato quando il dito viene rilasciato, quindi in ACTION_UPma con limitazioni: se è stato eseguito il gesto di lancio (strisciata), OnClickListenernon viene sparato ma ACTION_UPverrà comunque elaborato.
Alex Semeniuk

Sto cercando di scrivere del testo sulle coordinate cliccate. Ho provato a scrivere del testo alle coordinate (event.getX(), event.getY()) ma non sta scrivendo nella posizione corretta.
Prince


26

Esempio completo

Nelle altre risposte mancano alcuni dettagli. Ecco un esempio completo.

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);
        }
    };
}

Sommario

  • Aggiungi una variabile di classe per memorizzare le coordinate
  • Salva le coordinate X, Y usando un file OnTouchListener
  • Accedi alle coordinate X, Y nel file OnClickListener

1
Invece di un Array a virgola mobile di 2 spazi, è possibile utilizzare Point ().
ZooMagic

Il punto ha X e Y di tipo intero. Le coordinate sono valori float. Se uso la classe Point, penso che perderò la precisione ... Sono molto nuovo in Android e forse mi sono perso qualcosa.
mboada

@mboada, hai ragione. PointF sarebbe meglio.
Suragch

Ci dovrebbe essere un modo per evitare onTouchListener e usare solo onClickListener. In qualche modo, ContextMenu non ne ha bisogno. Facendo clic su un elemento e mostrando il menu con la vista come ancoraggio, sa dove metterlo, vicino alla posizione del tocco. Vedi qui: stackoverflow.com/q/57290574/878126 . Sai come è possibile? In tal caso, considera la possibilità di rispondere lì.
sviluppatore Android

3

Ignora onTouchEvent (MotionEvent ev)

Quindi puoi fare:

ev.getXLocation()

O qualcosa di simile. Avere un macellaio.


2
Ciao Tom, sì, possiamo usare onTouchEvent, ma poi dobbiamo gestire noi stessi il discernimento tra clic e clic lunghi, no? Non ha senso che non ti forniscano un modo per sapere dove si è verificato il clic o il clic lungo in OnClickListener, ecc.? Grazie
Mark

21
Tutto quello che devi fare è registrare la posizione x & y dell'ultimo evento ACTION_UP o ACTION_MOVE e utilizzare questi valori nel tuo OnClickListener.
Romain Guy,

@RomainGuy Ma devi anche calcolare la distanza tra i due punti per determinare un clic. Se ricevi l'evento ACTION_DOWN a (0,0) e quindi l'evento ACTION_UP a (100,100) non è sicuramente un clic.
TheRealChx101

@ chx101, quello che intendeva RomainGuy (penso) era che se solo su touchevent registri le ultime coordinate action_up, quelle sono le coordinate che puoi usare in onclick. tuttavia penso che in pratica sarebbe necessario creare una sottoclasse della vista, altrimenti l'onclick non viene chiamato. puoi anche rilevare il rubinetto come rilevatore di gesti come in stackoverflow.com/questions/19538747/… answer
Lassi Kinnunen

0

Puoi creare una funzione di estensione in Kotlin, in questo modo:

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)
    }
}

Se hai bisogno di un clic lungo, sostituisci setOnClickListener

Uso getLocationOnScreen()perché ho bisogno delle coordinate per ViewHolder di RecyclerView

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.