Tengo un problema con mi botón que permanece en un estado resaltado, después de hacer lo siguiente:
public class MainActivity extends AppCompatActivity {
@SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AppCompatButton button = (AppCompatButton) findViewById(R.id.mybutton);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Test", "calling onClick");
}
});
button.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
v.getBackground().setColorFilter(0xe0f47521,PorterDuff.Mode.SRC_ATOP);
v.invalidate();
break;
}
case MotionEvent.ACTION_UP: {
v.getBackground().clearColorFilter();
v.invalidate();
v.performClick();
Log.d("Test", "Performing click");
return true;
}
}
return false;
}
});
}
}
Con respecto al código anterior, cuando lo uso, espero que el clic del botón se maneje con el tacto, y al devolver "verdadero" el manejo debería detenerse en el touchListener.
Pero este no es el caso. El botón permanece en un estado resaltado, aunque se llame al clic.
Lo que obtengo es:
Test - calling onClick
Test - Performing click
Por otro lado, si estoy usando el siguiente código, se hace clic en el botón, se imprime lo mismo, pero el botón no termina atascado en un estado resaltado:
public class MainActivity extends AppCompatActivity {
@SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AppCompatButton button = (AppCompatButton) findViewById(R.id.mybutton);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Test", "calling onClick");
}
});
button.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
v.getBackground().setColorFilter(0xe0f47521,PorterDuff.Mode.SRC_ATOP);
v.invalidate();
break;
}
case MotionEvent.ACTION_UP: {
v.getBackground().clearColorFilter();
v.invalidate();
// v.performClick();
Log.d("Test", "Performing click");
return false;
}
}
return false;
}
});
}
}
Estoy un poco confundido sobre cuál es la cadena de respuesta al evento táctil. Mi conjetura es que es:
1) TouchListener
2) ClickListener
3) ParentViews
¿Alguien puede confirmar esto también?
android
onclicklistener
android-button
ontouchlistener
Oso blanco
fuente
fuente

Respuestas:
Dichas personalizaciones no necesitan modificaciones programáticas. Puedes hacerlo simplemente en
xmlarchivos. En primer lugar, elimine elsetOnTouchListenermétodo que proporciona en suonCreatetotalidad. A continuación, defina un color selector en elres/colordirectorio como el siguiente. (si el directorio no existe, créelo)res / color / button_tint_color.xml
Ahora, configúrelo en el
app:backgroundTintatributo del botón :Resultado visual:
EDITADO: (para abordar el problema del evento táctil)
Desde un punto de vista general, el flujo del evento táctil comienza desde
Activity, luego fluye hacia el diseño (desde los diseños principales hasta los secundarios) y luego hacia las vistas. (Flujo LTR en la siguiente imagen)Cuando el evento tacto llega a la vista de destino, la vista puede controlar el evento luego decidir pasarlo a los diseños antes / actividad o no (volviendo
falsedetrueenonTouchel método). (Flujo RTL en la imagen de arriba)Ahora echemos un vistazo al código fuente de la Vista para obtener una visión más profunda de los flujos de eventos táctiles. Al echar un vistazo a la implementación de la
dispatchTouchEvent, veremos que si configuras unaOnTouchListenervista y luego regresastrueen suonTouchmétodo,onTouchEventno se llamará a la vista.Ahora, mire el
onTouchEventmétodo donde está la acción del eventoMotionEvent.ACTION_UP. Vemos que la acción de hacer clic ocurre allí. Por lo tanto, regresartrueen elOnTouchListener'sonTouchy, en consecuenciaonTouchEvent, no llamar alOnClickListener' hace que no se llame al 'sonClick.Hay otro problema con no llamar al
onTouchEvent, que está relacionado con el estado presionado y que mencionó en la pregunta. Como podemos ver en el siguiente bloque de código, hay una instancia deUnsetPressedStateesas llamadas cuando se ejecuta. El resultado de no llamar es que la vista se atasca en el estado presionado y su estado de dibujo no cambia.setPressed(false)setPressed(false)UnsetPressedState :
Con respecto a las descripciones anteriores, puede cambiar el código llamándose a
setPressed(false)sí mismo para cambiar el estado dibujable donde está la acción del eventoMotionEvent.ACTION_UP:fuente
Now, look at the onTouchEvent method where the event action is MotionEvent.ACTION_UP. We see that perform-click action happens there. So, returning true in the OnTouchListener's onTouch and consequently not calling the onTouchEvent, causes not calling the OnClickListener's onClick.en mi caso se llama a onClick mUnsetPressedState comprueba si es nulo antes de establecerlo en falso y tampoco se puede ejecutar el ejecutable si estamos preimpresos. Yo no entiendo muy bien cómo se deduce que debe establecerse en falseonClickllama porque estás llamandov.performClick();. Compruebe el código anterior en laMotionEvent.ACTION_UPsección nuevamente,setPressed(false)se llama de todos modos, simUnsetPressedStatees nulo o no, siprepressedes verdadero o no. La diferencia está en la forma de llamar asetPressed(false)que podría ser a través depost/postDelayedo directamente.Estás jugando
touchyfocuseventos. Comencemos por comprender el comportamiento con el mismo color. De manera predeterminada, seSelectorasigna como fondo aButtonAndroid. Entonces, simplemente cambiando el color de fondo, make es estático (el color no cambiará). Pero no es un comportamiento nativo.Selectorpodría parecerse a este.Como puede ver arriba, hay estado
focusedy estadopressed. Al configuraronTouchListener, manejará los eventos táctiles, que no tienen nada que verfocus.Selectordel botón debe reemplazar elfocusevento con un eventotouchdurante el clic en el botón. Pero en la primera parte de su código, interceptó eventos para eltouch(retorno verdadero de la devolución de llamada). El cambio de color no puede continuar y se congela con el mismo color. Y es por eso que la segunda variante (sin intercepción) está funcionando bien y esa es su confusión.ACTUALIZAR
Todo lo que necesita hacer es cambiar el comportamiento y el color de la
Selector. Por ej. utilizando el siguiente fondo para elButton. Y eliminaronTouchListenerde su implementación en absoluto.fuente
onTouchListeners como desee. Simplemente no necesita consumir eventos, porreturn true.backgroundColor.Si asigna un fondo al botón, no cambiará el color al hacer clic.
y configúralo como fondo para tu botón
fuente
solo puede usar chips de material para en lugar de la vista de botones. consulte: https://material.io/develop/android/components/chip allí manejan esos eventos hililghted y puede personalizar con la aplicación de los temas.
fuente