Alexandr
Alexandr

Reputation: 3969

How do I set the disabled color of a button with AppCompat?

I use this style to change the background color of my Button:

<style name="AccentButton" parent="Widget.AppCompat.Button.Colored">
    <item name="colorButtonNormal">@color/colorAccent</item>
    <item name="android:textColor">@color/white</item>
</style>

And in layout:

    <Button
        android:id="@+id/login_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/fragment_login_login_button"
        app:theme="@style/AccentButton"/>

It works. But when I call setEnabled(false) on this Button, it keeps the same color. How can I manage this case?

Upvotes: 44

Views: 56146

Answers (7)

ChrisPrime
ChrisPrime

Reputation: 468

Kotlin implementation of @meanman's answer above, adjusting alpha is by far the simplest way to go and all my touch ripple effects still work as before:

import android.content.Context
import android.support.v7.widget.AppCompatButton
import android.util.AttributeSet

class FadedDisableButton : AppCompatButton {
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    override fun setEnabled(enabled: Boolean) {
        alpha = when {
            enabled -> 1.0f
            else -> 0.5f
        }
        super.setEnabled(enabled)
    }
}

Upvotes: 1

Seven
Seven

Reputation: 3262

Complete solution extending from ianhanniballake' answer and Joe Bowbeer' comment:

/res/values/styles.xml

<style name="AccentButton" parent="ThemeOverlay.AppCompat.Dark">
    <!-- customize colorAccent for the enabled color -->
    <!-- customize colorControlHighlight for the enabled/pressed color -->
    <!-- customize colorButtonNormal for the disabled color -->
    <item name="android:buttonStyle">@style/Widget.AppCompat.Button.Colored</item>
</style>

And wherever you use the button:

<Button
    android:id="@+id/login_button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/fragment_login_login_button"
    android:theme="@style/AccentButton"/>

That worked really nice for me

Upvotes: 3

ianhanniballake
ianhanniballake

Reputation: 200080

You aren't using the Widget.AppCompat.Button.Colored style correctly. You're using a parent style (Widget.AppCompat.Button.Colored), but applying it as a theme. This effectively means that the Widget.AppCompat.Button.Colored part is being ignored entirely and you are instead just changing the default color of the button (which works, but doesn't handle the disabled case).

Instead, you should use a ThemeOverlay and apply the Colored style separately:

<style name="AccentButton" parent="ThemeOverlay.AppCompat.Dark">
   <!-- customize colorButtonNormal for the disable color -->
   <!-- customize colorAccent for the enabled color -->
</style>

<Button
    android:id="@+id/login_button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/fragment_login_login_button"
    android:theme="@style/AccentButton"
    style="@style/Widget.AppCompat.Button.Colored"/>

As mentioned in this answer on using the Widget.AppCompat.Button.Colored style, the disabled color is controlled by colorButtonNormal and the enabled color is controlled by colorAccent. By using the ThemeOverlay.AppCompat.Dark, the textColor is automatically changed to dark, meaning you may not need the custom ThemeOverlay at all.

Upvotes: 89

Milan Hlin&#225;k
Milan Hlin&#225;k

Reputation: 4430

Currently, I use the following settings for Android API 15+.

/res/color/btn_text_color.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:color="#42000000" android:state_enabled="false" />
  <item android:color="#ffffff" />
</selector>

/res/values/styles.xml

<style name="ColoredButton" parent="Widget.AppCompat.Button.Colored">
    <item name="android:textColor">@color/btn_text_color</item>
</style>

and

<Button
    android:id="@+id/button"
    style="@style/ColoredButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="button" />

Upvotes: 12

Meanman
Meanman

Reputation: 1544

Combining the accepted solution with a custom widget we can have a button which appears disabled by setting the alpha. This should work for any button and text color combination:

public class ButtonWidget extends AppCompatButton {

    public ButtonWidget(Context context) {
        super(context);
    }

    public ButtonWidget(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ButtonWidget(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void setEnabled(boolean enabled) {
        setAlpha(enabled ? 1 : 0.5f);
        super.setEnabled(enabled);
    }

}

Upvotes: 13

Amit Vaghela
Amit Vaghela

Reputation: 22965

When you have changed programatically you need to act that way:

button = new Button(new ContextThemeWrapper(ActiVityName.this, R.style.AccentButton));

OR

if (button.isEnabled())
    button.getBackground().setColorFilter(Color.Black, PorterDuff.Mode.MULTIPLY);
else
    button.getBackground().setColorFilter(null);

Upvotes: 7

Awais Ahmad
Awais Ahmad

Reputation: 427

instead of using color for your button, you should use a background with selectors. Here is the demo code

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="true">
        <shape android:shape="rectangle">
            <solid android:color="@color/yourEnabledColor" />
        </shape>
    </item>
    <item android:state_enabled="false">
        <shape android:shape="rectangle">
            <solid android:color="@color/yourDisabledColor" />
        </shape>
    </item>
</selector>

Upvotes: 16

Related Questions