"Presione y mantenga presionado" en Android necesita cambiar estados (selector XML personalizado) usando onTouchListener

Tengo un gráfico de botón que necesita tener "presionar y mantener" la funcionalidad, así que en lugar de usar onClickListener, estoy usando onTouchListener para que la aplicación pueda reaccionar a

MotionEvent.ACTION_DOWN, 

y

  MotionEvent.ACTION_UP 

Dependiendo de la rapidez con que se desencadenen estos dos eventos, puedo ejecutar un "pressAndHoldHandler" en el tiempo entre los dos.

De todos modos, larga historia corta: Tengo numerosos "básicos" botones en la misma aplicación que no requieren la prensa y mantener la funcionalidad, por lo que están utilizando el onClickListener.

Cada uno de estos botones se han personalizado gráficamente con su propio archivo 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: El selector anterior no se accede con el onTouchListener. Sólo el onClickListener extraerá los cambios de estado con la sección onClick () de su propio método, por lo que estos botones "presionar y mantener" nunca cambian de estado. Comentarios bastante terribles para el usuario.

Actualmente estoy forzando lo anterior dentro del caso 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 hack, y falta la etapa "enfocada pero no presionada".

¿Alguien tropezó con esto antes?

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

Probablemente desee habilitar el estado Presionado cuando obtenga el evento ACTION_DOWN y deshabilitarlo cuando obtenga el evento ACTION_UP .

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

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

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

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

PS No es necesario que todos los estados en el selector se puede utilizar 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> 

¡Me lo imaginé! Sólo use view.setSelected() como sigue:

 @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 🙂

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); } 
  • Desactivar el color de resaltado de fondo del elemento de menú en android
  • Fondo de color de fondo de Android Textview
  • Selector de fecha en Android
  • Elemento de ListView Estado de LongClick para el selector
  • Android cómo aplicar forma y selector simultáneamente para Button
  • ¿Cuál es el valor predeterminado para presionar un elemento de lista
  • ¿Cómo configurar diferentes temas para el selector de botones?
  • Mostrar selector de fechas con mes y año sólo para lollipop 5.0 en android
  • Aplicaciones de Android: Recuperación del contacto "Me" de la lista de contactos
  • Cómo configurar el tono de timbre con RingtoneManager.ACTION_RINGTONE_PICKER?
  • ¿Por qué android: listSelector cambia incorrectamente de Actividad a Actividad
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.