studio example event developer action_outside android selector ontouchlistener onclicklistener

example - El botón "Mantener presionado" en Android necesita cambiar de estado(selector XML personalizado) usando onTouchListener



touch en android studio (5)

¡Me lo imaginé! Simplemente use view.setSelected() siguiente manera:

@Override public boolean onTouch(View v, MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_DOWN){ yourView.setSelected(true); ... return true; } else if(event.getAction() == MotionEvent.ACTION_UP){ yourView.setSelected(false); ... return true; } else return false; }

Eso hará que su selector funcione incluso si su vista tiene un oyente onTouch :)

Tengo un gráfico de botón que debe tener la funcionalidad de "mantener presionado", por lo que en lugar de usar onClickListener, estoy usando onTouchListener para que la aplicación pueda reaccionar.

MotionEvent.ACTION_DOWN,

y

MotionEvent.ACTION_UP

Dependiendo de qué tan rápido se activen esos dos eventos, puedo ejecutar un "pressAndHoldHandler" en el tiempo entre los dos.

De todos modos, cuento largo: tengo numerosos botones "básicos" en la misma aplicación que no requieren la función de presionar y mantener, por lo que están usando onClickListener.

Cada uno de estos botones se ha personalizado gráficamente con su propio archivo de selector XML:

<?xml version="1.0" encoding="UTF-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="false" android:drawable="@drawable/btn_chicken_off" /> <item android:state_enabled="true" android:state_pressed="true" android:drawable="@drawable/btn_chicken_s3" /> <item android:state_enabled="true" android:state_focused="true" android:drawable="@drawable/btn_chicken_s2" /> <item android:state_enabled="true" android:drawable="@drawable/btn_chicken_off" /> </selector>

Por lo tanto, el problema aquí es: no se puede acceder al selector anterior con onTouchListener. Solo el onClickListener activará los cambios de estado con la sección onClick () de su propio método, por lo que estos botones de "mantener presionado" nunca cambian de estado. Bastante terrible comentario para el usuario.

Actualmente estoy forzando lo anterior dentro del caso de cambio de ACTION_DOWN y ACTION_UP haciendo lo siguiente:

if (action == MotionEvent.ACTION_DOWN) { btn_chicken.setBackgroundResource(R.drawable.btn_chicken_s3); } else if (action == MotionEvent.ACTION_UP) { btn_chicken.setBackgroundResource(R.drawable.btn_chicken_off); }

Pero parece un truco, y falta la etapa de "enfocado pero no presionado".

¿Alguien se tropezó con esto antes?


Asegúrese de devolver false al final de la función onTouchListener (). :)


Mejor solución:

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:state_activated="true"> <bitmap android:src="@drawable/image_selected"/> </item> <item> <bitmap android:src="@drawable/image_not_selected"/> </item> </selector> @Override public void onClick(View v) { if (v.isActivated()) v.setActivated(false); else v.setActivated(true); }


Simplemente puede configurar el botón onClickListener y dejar su método onClick vacío. Su lógica implementa dentro de onTouch. De esa manera tendrás el efecto de prensa.

PS No necesitas todos esos estados en el selector que puedes usar simplemente:

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:state_pressed="true" android:drawable="@drawable/IMAGE_PRESSED" /> <item android:drawable="@drawable/IMAGE" /> </selector>


Use la función view.setPressed() para simular el comportamiento presionado por usted mismo.

Probablemente desearía habilitar el estado Presionado cuando obtenga el evento ACTION_DOWN y deshabilitarlo cuando obtenga el evento ACTION_UP .

Además, será una buena idea deshabilitarlo en caso de que el usuario salga del botón. Captura el evento ACTION_OUTSIDE , como se muestra en el siguiente ejemplo:

@Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: v.setPressed(true); // Start action ... break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_OUTSIDE: case MotionEvent.ACTION_CANCEL: v.setPressed(false); // Stop action ... break; case MotionEvent.ACTION_POINTER_DOWN: break; case MotionEvent.ACTION_POINTER_UP: break; case MotionEvent.ACTION_MOVE: break; } return true; }