10
votes

I'm trying to figure out how I can change the background color of the floating action button when it is disabled for a duration of 2 seconds after being pressed. I would also like it to return to its original color when the 2 second duration is over.

This is the code for the 2 second delay when pressed. This code is in a fragment within the MainActivity.

 appBar.setExpanded(true, true);
 fab.setVisibility(View.VISIBLE);
 fab.setImageResource(R.drawable.ic_phone_white_18dp);

 fab.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
     fab.setClickable(false);
     Timer buttonTimer = new Timer();
     buttonTimer.schedule(new TimerTask() {
       @Override
       public void run() {
         runOnUiThread(new Runnable() {
           @Override
           public void run() {
             fab.setClickable(true);
           }
         });
       }
     }, 2000);

I've tried playing around with the StateListDrawable methods in the documentation but have not come across anything that works.

This is the XML for the color themes of the FAB

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/themeColorPressed" android:state_pressed="true"/>
    <item android:color="@color/themeColorPressed" android:state_checked="true"/>
    <item android:color="@color/themeColorPressed" android:state_selected="true"/>
    <item android:color="@color/themeColorPressed" android:state_enabled="false"/>
    <item android:color="@color/themeColor" android:state_enabled="true"/>
</selector>
4

4 Answers

4
votes

Just call fab.setBackgroundColor(Color.GRAY); (or whatever color) when you disable it. Also you can use fab.setBackgroundColor(getResources().getColor(R.color.colorAccent0)); to use a resource color.

3
votes

Just use as app:backgroundTint a selector as:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:color="...." android:state_enabled="true"/>
  <item android:alpha="..." android:color="...."/>
</selector>

And then just use in your code:

fab.isEnabled = true
fab.isEnabled = false
2
votes

I just found something that works well...

Firstly I moved the setEnabled() method in the selector XML of the button theme atleast above the color declaration like so.

<?xml version="1.0" encoding="utf-8"?>

<item android:color="@color/themeColorPressed" android:state_pressed="true"/>
<item android:color="@color/themeColorPressed" android:state_checked="true"/>
<item android:color="@color/themeColorPressed" android:state_selected="true"/>
<item android:color="@color/grey" android:state_enabled="false"/>
<item android:color="@color/themeColor"/>

Setting it initially to false for that respected color it's assigned to.

Then in the Java code, just call the setEnabled method on the button you're targerting (fab in this case) and use a boolean value to dictate whether its activated or deactivated in the onClick method:

                                fab.setClickable(false);
                                fab.setEnabled(false);
                                Timer buttonTimer = new Timer();
                                buttonTimer.schedule(new TimerTask() {
                                    @Override
                                    public void run() {
                                        runOnUiThread(new Runnable() {
                                            @Override
                                            public void run() {
                                                fab.setClickable(true);
                                                fab.setEnabled(true);
                                            }
                                        });
                                    }
                                }, 2000);
1
votes

Looking at the implementation of the FloatingActionButton, the fab.setBackgroundColor(int color) method is not supported.

I managed to change the color of the FAB with the following method (in Kotlin):

private fun toggleFabEnabled(enabled: Boolean){
    fab.isEnabled = enabled
    if (enabled){
        fab.backgroundTintList = ColorStateList.valueOf(resources.getColor(R.color.colorAccent, null))
    } else {
        fab.backgroundTintList = ColorStateList.valueOf(resources.getColor(R.color.disabled, null))
    }
}

For API < 23 get the color with the following method resources.getColor(R.color.disabled)

How I handle the different API methods is I create an extension function in Kotlin that handles all APIs.