¿Cómo atenuar un botón?

103

Tengo un botón definido como se muestra a continuación. Cuando quiero desactivarlo lo uso my_btn.setEnabled(false), pero también me gustaría atenuarlo. ¿Cómo puedo hacer eso?

Gracias

<Button android:id="@+id/buy_btn" style="@style/srp_button" />

style / srp_button

<style name="srp_button" parent="@android:style/Widget.Button">
    <item name="android:background">@drawable/btn_default</item>
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:textColor">#ffffff</item>
    <item name="android:textSize">14sp</item>
    <item name="android:typeface">serif</item>
    <item name="android:paddingLeft">30dp</item>
    <item name="android:paddingRight">30dp</item>
    <item name="android:paddingTop">5dp</item>
    <item name="android:paddingBottom">5dp</item>
</style>

drawable / btn_default.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/pink" />
    <corners android:radius="6dp" />
</shape>
jul
fuente

Respuestas:

57

Debe proporcionar 3 o 4 estados en su btn_defaut.xmlcomo selector.

  1. Estado presionado
  2. Estado predeterminado
  3. Estado de enfoque
  4. Estado habilitado (estado deshabilitado con indicación falsa; ver comentarios)

Proporcionará efectos y antecedentes para los estados en consecuencia.

Aquí hay una discusión detallada: Botón estándar de Android con un color diferente

Adil Soomro
fuente
Entonces, para atenuarlo, ¿debo cambiar el color del fondo Y el color del texto en el estado de desactivación? ¿No hay forma de simplemente agregar un primer plano transparente?
julio
3
¡Sí! lo que proporcionará android:state_disable="true"mostrará el estado cuando el Botón está desactivado, de la manera más fácil y recomendada.
Adil Soomro
y ¿dónde puedo especificar el color del texto para el estado desactivado? Parece que solo se puede especificar un fondo ... Hice una nueva pregunta para eso: stackoverflow.com/questions/8743584/…
julio
17
No hay android:state_disable="true", ¿verdad? ¿Te refieres a android:state_enabled="false"?
caw
@MarcoW .: sí, tienes toda la razón. Disculpas por el atributo equivocado.
Adil Soomro
171

También puede hacer que aparezca como deshabilitado configurando el alfa (haciéndolo semitransparente). Esto es especialmente útil si el fondo de su botón es una imagen y no desea crear estados para ella.

button.setAlpha(.5f);
button.setClickable(false);

actualización: escribí la solución anterior antes de Kotlin y cuando era un novato. Es más una solución "rápida y sucia", pero no la recomiendo en un entorno profesional.

Hoy, si quisiera una solución genérica que funcione en cualquier botón / vista sin tener que crear una lista de estados, crearía una extensión de Kotlin.

fun View.disable() {
    getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY)
    setClickable(false)
}

En Java, puede hacer algo similar con una función util estática y solo tendría que pasar la vista como variable. No es tan limpio pero funciona.

Siavash
fuente
4
Había leído que las llamadas a setAlpha son caras en la CPU. ¿Alguien puede confirmar?
Ali Kazi
@AliKazi depende del tipo de tu View. Desde este puesto de G + : "Si su vista no contiene comandos de dibujo se superponen, setAlpha()se ha optimizado de distancia y simplemente modificar los objetos para aplicar el alfa adecuada la pintura Esto sucede cuando. View.hasOverlappingRendering()Retornos cierto. ImageViewS, y TextViewes que no tienen antecedentes dibujable son candidatos comunes para este optimización. Si se encuentra en esta situación, utilice la setAlpha()cantidad que desee ".
Sufian
1
@Sufian Gracias. Pero para estar más seguro, confié en un StateListDrawable simple para cada botón. Cómo hice eso, lo publiqué como una nueva respuesta. Incluí enlaces a donde aprendí que el alfa es malo para el rendimiento.
Ali Kazi
Visualmente desagradable para el usuario
Farid
que en realidad deshabilitan visualmente la vista. gracias @Siavash
Akash Bisariya
54

La solución más fácil es configurar el filtro de color en la imagen de fondo de un botón como vi aquí.

Puedes hacer lo siguiente:

if ('need to set button disable')
    button.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY);
else
    button.getBackground().setColorFilter(null);

Espero haber ayudado a alguien ...

Leñoso
fuente
Me gusta más este enfoque. ¡Gracias!
nab
2
Este enfoque tiene potencial, pero el color resultante no siempre es el que crees que será. Por ejemplo, un botón naranja con el color gris multiplicado da como resultado un color rojo oscuro, no un naranja descolorido.
Someone Somewhere
4
tal vez Mode.SRC_INdebería usarse en lugar de Multiplicar. Ver stackoverflow.com/a/17112876/550471
Someone Somewhere
Esto funciona, pero dos colores cuando se mezclan se convierten en otro color
Shamsul Arefin Sajib
¡Increíble! muy limpio.
Milind Chaudhary
21

Todas las respuestas dadas funcionan bien, pero recuerdo haber aprendido que usar setAlpha puede ser una mala idea en cuanto al rendimiento (más información aquí ). Entonces, crear un StateListDrawable es una mejor idea para administrar el estado deshabilitado de los botones. Así es cómo:

Cree un XML btn_blue.xml en la carpeta res / drawable:

<!-- Disable background -->
<item android:state_enabled="false"
      android:color="@color/md_blue_200"/>

<!-- Enabled background -->
<item android:color="@color/md_blue_500"/>

Cree un estilo de botón en res / values ​​/ styles.xml

<style name="BlueButton" parent="ThemeOverlay.AppCompat">
      <item name="colorButtonNormal">@drawable/btn_blue</item>
      <item name="android:textColor">@color/md_white_1000</item>
</style>

Luego aplique este estilo a su botón:

<Button
     android:id="@+id/my_disabled_button"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:theme="@style/BlueButton"/>

Ahora, cuando llame a btnBlue.setEnabled(true)O, btnBlue.setEnabled(false)los colores del estado cambiarán automáticamente.

Ali Kazi
fuente
12

Establezca Clickable como falso y cambie el color de fondo como:

callButton.setClickable(false);
callButton.setBackgroundColor(Color.parseColor("#808080"));
Saty
fuente
12

Debe crear un archivo XML para el botón deshabilitado ( drawable / btn_disable.xml )

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/grey" />
    <corners android:radius="6dp" />
</shape>

Y crea un selector para el botón ( drawable / btn_selector.xml )

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/btn_disable" android:state_enabled="false"/>
    <item android:drawable="@drawable/btn_default" android:state_enabled="true"/>
    <item android:drawable="@drawable/btn_default" android:state_pressed="false" />

</selector>

Agrega el selector a tu botón

<style name="srp_button" parent="@android:style/Widget.Button">
    <item name="android:background">@drawable/btn_selector</item>
</style>
Willy Chen
fuente
2
Button button = (Button)findViewById(R.id.buy_btn);
button.setEnabled(false);
Leon van Noord
fuente
13
Eso no responde la pregunta.
Quality Catalyst
1

Usé este código para eso:

ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
profilePicture.setColorFilter(filter);
Dominik
fuente
0

Probé las soluciones anteriores, pero ninguna de ellas pareció funcionar para mí. Fui con la siguiente opción:

<!-- button_color_selector.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/colorAccent" android:state_enabled="true"/>
    <item android:color="@color/colorAccentLight" android:state_enabled="false"/>
</selector>
<com.google.android.material.button.MaterialButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:backgroundTint="@color/button_color_selector"
                .../>
André Ramon
fuente