Search code examples
androidanimationandroid-actionbarandroid-actionbar-compat

Android - Is there any way to toggle ActionBar icon with animation?


I have a DrawerLayout in my app and a custom icon in the ActionBar. When the menu is opened, the icon is not visible. Once the menu is closed again, the icon re-appears. Right now, it just shows\disappears instantly. I would like to add fade animations to the icon. Is there any way to achieve this effect?

This code is currently used to toggle the icon:

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    if(!drawerOpened){
        inflater.inflate(R.menu.chats_activity_action, menu);
    } else {
        actionBar.setDisplayUseLogoEnabled(false);
    }
    return true;
}

This is how the icon is defined within an XML file:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto" >
    <item
        android:id="@+id/menu_filter"
        android:title="Add a user"
        app:showAsAction="always"
        android:icon="@drawable/plus_icon"/>
</menu>

Solution

  • First, make the MenuItem invisible in your layout:

    <item
        android:id="@+id/menu_filter"
        android:title="Add a user"
        app:showAsAction="always"
        android:icon="@drawable/plus_icon"
        android:visible="false"/> <!-- New attribute -->
    

    Then modify your onCreateOptionsMenu:

    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        if(!drawerOpened){
            inflater.inflate(R.menu.chats_activity_action, menu);
    
            final MenuItem item = menu.findItem(R.id.menu_filter);
    
            // Post delayed so the view can be built,
            // otherwise findViewById(R.id.menu_filter) would be null
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    AlphaAnimation animation = new AlphaAnimation(0.0f, 1.0f);
                    animation.setDuration(1000);
    
                    // Make item visible and start the animation
                    item.setVisible(true);
                    findViewById(R.id.menu_filter).startAnimation(animation);
                }
            }, 1);
        } else{
            actionBar.setDisplayUseLogoEnabled(false);
    
    
            inflater.inflate(R.menu.chats_activity_action, menu);
            final MenuItem item = menu.findItem(R.id.menu_filter);
            item.setVisible(true);
    
            // Post delayed so the view can be built,
            // otherwise findViewById(R.id.menu_filter) would be null
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    AlphaAnimation animation = new AlphaAnimation(0.1f, 0.0f);
                    animation.setFillEnabled(true);
                    animation.setFillAfter(true);
                    animation.setDuration(1000);
    
                    // start the animation
                    findViewById(R.id.menu_filter).startAnimation(animation);
                }
            }, 1);
    
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    item.setVisible(false);
                }
            }, 1000); // The animation is finished after 1000ms
        }
        return true;
     }
    

    Basically, the item is inflated even if the drawer is open. Afterwards, the item gets faded out with an animation and set to invisible after the animation is over.