studio programacion herramientas fundamentos con avanzado aplicaciones android listeners ontouchlistener

programacion - manual de android en pdf



No se pueden manejar los eventos de clic y toque simultáneamente (9)

Estoy tratando de manejar eventos táctiles y hacer clic en eventos en un botón. Yo hago lo siguiente:

button.setOnClickListener(clickListener); button.setOnTouchListener(touchListener);

Cuando un oyente está registrado, las cosas funcionan bien, pero cuando trato de usarlas, solo se activan los eventos táctiles. Cualquier solución? ¿Qué estoy haciendo mal?


Debería devolver el valor falso en su OnTouchListener entonces su OnClickListener también se manejará.


Es un poco complicado.

Si configura onTouchListener , debe devolver true en ACTION_DOWN , para indicar al sistema que he consumido el evento y que no se filtrará a otros oyentes.

Pero entonces OnClickListener no será despedido.

Así que puedes pensar, solo haré lo mío allí y devolveré el valor false para que pueda recibir clics también. Si lo haces, funcionará, pero no estarás suscrito a otros eventos táctiles próximos ( ACTION_MOVE , ACTION_UP ). Por lo tanto, la única opción es regresar allí, pero no recibirás ningún evento de clic como dijimos. previamente.

Por lo tanto, debe realizar el clic manualmente en ACTION_UP con view.performClick()

Esto funcionará.


Gracias a @urSus por una gran respuesta.
Pero en ese caso, cada toque realizará un clic, incluso ACTION_MOVE
Suponiendo que desee separar move evento de move y el evento de click , puede utilizar un pequeño truco
define un campo boolean y usa así:

@Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: shouldClick = true; . . break; case MotionEvent.ACTION_UP: if (shouldClick) view.performClick(); break; case MotionEvent.ACTION_POINTER_DOWN: break; case MotionEvent.ACTION_POINTER_UP: break; case MotionEvent.ACTION_MOVE: //Do your stuff shouldClick = false; break; } rootLayout.invalidate(); return true; }


Hay una diferencia sutil, pero muy importante entre el ClickListener y el TouchListener . El TouchListener se ejecuta antes de que la vista pueda responder al evento. El ClickListener recibirá su evento solo después de que la vista lo haya manejado.

Por lo tanto, cuando toca su pantalla, TouchListener se ejecuta el TouchListener y cuando devuelve true para su evento, el ClickListener nunca lo obtendrá. Pero si presiona el trackball de su dispositivo, el ClickListener debe ser TouchListener porque el TouchListener no responderá.


Para hacer que ambos eventos sean posibles en la vista de cuadrícula, solo al hacer que el escucha del tacto sea "falso" de la siguiente manera, esto funcionó para mí.

**GridView myView = findViewById(R.id.grid_view); myView.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { // ... Respond to touch events return false; } });**

De esta manera se pueden lograr ambos eventos.


Supongo que estás volviendo true en tu OnTouchListener ? Eso consumirá el evento por lo que no se enviará hacia abajo para cualquier procesamiento posterior.

En una nota al margen: ¿cuál es el punto de tener tanto un oyente de clic como de toque?


Toda la respuesta anterior dice que no podemos manejar tanto setOnTouchListener como setOnClickListener .
Sin embargo, veo que podemos manejar ambos return false en setOnTouchListener

Ejemplo

override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) button = findViewById(R.id.button) button.setOnClickListener { Log.i("TAG", "onClick") } button.setOnTouchListener { v, event -> Log.i("TAG", "onTouch " + event.action) false } }

Cuando hago clic en el Button , Logcat se mostrará como

I/TAG: onTouch 0 I/TAG: onTouch 1 I/TAG: onClick


## Exact working solution for both click action and touch listener(dragging) ## private int initialX; private int initialY; private float initialTouchX; private float initialTouchY; private float CLICK_ACTION_THRESHOLD = 0.5f; private float startX; private float startY; @Override public boolean onTouch(View view, MotionEvent event) { switch (view.getId()) { case R.id.chat_head_profile_iv: switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //remember the initial position. initialX = params.x; initialY = params.y; startX = event.getX(); startY = event.getY(); //get the touch location initialTouchX = event.getRawX(); initialTouchY = event.getRawY(); return true; case MotionEvent.ACTION_UP: float endX = event.getX(); float endY = event.getY(); if (shouldClickActionWork(startX, endX, startY, endY)) { openScreen();// WE HAVE A CLICK!! } return true; case MotionEvent.ACTION_MOVE: //Calculate the X and Y coordinates of the view. params.x = initialX + (int) (event.getRawX() - initialTouchX); params.y = initialY + (int) (event.getRawY() - initialTouchY); //Update the layout with new X & Y coordinate mWindowManager.updateViewLayout(mChatHeadView, params); return true; } break; } return true; } private boolean shouldClickActionWork(float startX, float endX, float startY, float endY) { float differenceX = Math.abs(startX - endX); float differenceY = Math.abs(startY - endY); if ((CLICK_ACTION_THRESHOLD > differenceX) && (CLICK_ACTION_THRESHOLD > differenceY)) return true; else return false; }


button.setOnTouchListener(this);

Implementar la interfaz y el código aquí:

@Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (view.getId()) { case R.id.send: switch(motionEvent.getAction()){ case MotionEvent.ACTION_DOWN: //when the user has pressed the button //do the needful here break; case MotionEvent.ACTION_UP: //when the user releases the button //do the needful here break; } break; } return false; }