Clans / FloatingActionButton

Android Floating Action Button based on Material Design specification
Apache License 2.0
5.22k stars 1.13k forks source link

Change action of the main FAB after opening the menu #430

Open mpivchev opened 6 years ago

mpivchev commented 6 years ago

How can I change the action of the main FAB after opening the menu, kind of like how Inbox does it:

image

Croutonix commented 6 years ago

See my comment on issue #52. To set a label on the menu button you can use fab:menu_fab_label="Compose". If you want to also change the color, you can add that it the animation listener used in my comment on the issue:

scaleInX.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationStart(Animator animation) {
        if (fabMenu.isOpened()) {
            fabMenu.getMenuIconView().setImageDrawable(iconClosed);
            fabMenu.setMenuButtonColorNormal(colorClosed);
        } else {
            fabMenu.getMenuIconView().setImageDrawable(iconOpened);
            fabMenu.setMenuButtonColorNormal(colorOpened);
        }
    }
});
mpivchev commented 6 years ago

@Croutonix I know about this, but I want to change the action that the button is going to do. I don't want the button to close the fab menu, I want it to do something else. Why would I have a button with a label "Compose" when it won't actually compose anything

Croutonix commented 6 years ago

Try this, it worked for me;

fabMenu.setOnMenuButtonClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if (fabMenu.isOpened()) {
            // Menu is opened and menu button was clicked
        }

        fabMenu.toggle(true);
    }
});
mpivchev commented 6 years ago

@Croutonix Thanks, I'll try this

mpivchev commented 6 years ago

@Croutonix what about changing the icon with the current rotation animation?

mpivchev commented 6 years ago

@Croutonix You removed your example, was there something wrong with it?

Croutonix commented 6 years ago

Yes sorry, but there was a problem with, fabMenu.getIconToggleAnimatorSet() returns null and not the default animation. You could always change the icon in the click listener like this:

if (fabMenu.isOpened()) {
    // set icon for closed state
} else {
    // set icon for opened state
}
fabMenu.toggle(true);

The problem with this is that it isn't called if you manually close the menu with fabMenu.close(true). You could also try setting a custom animation that is the same of the default animation.

Here's the implementation of the default animation:

private static final int ANIMATION_DURATION = 300;
private static final int ROTATION_ANGLE = -45f;

private AnimatorSet openAnimatorSet;
private AnimatorSet closeAnimatorSet;

private void createDefaultIconAnimation() {
    openAnimatorSet = new AnimatorSet();
    closeAnimatorSet = new AnimatorSet();

    ObjectAnimator collapseAnimator = ObjectAnimator.ofFloat(mImageToggle, "rotation", -90f + ROTATION_ANGLE, 0f);
    ObjectAnimator expandAnimator = ObjectAnimator.ofFloat(mImageToggle, "rotation", 0f, -90f + ROTATION_ANGLE);

    openAnimatorSet.play(expandAnimator);
    closeAnimatorSet.play(collapseAnimator);

    openAnimatorSet.setInterpolator(mOpenInterpolator);
    closeAnimatorSet.setInterpolator(mCloseInterpolator);

    openAnimatorSet.setDuration(ANIMATION_DURATION);
    closeAnimatorSet.setDuration(ANIMATION_DURATION);
}

Then you have to call fabMenu.setIconToggleAnimatorSet(openAnimatorSet) when you want to open the menu and fabMenu.setIconToggleAnimatorSet(closeAnimatorSet) when you want to close it.

In theory that works.

null1099 commented 6 years ago

Here's my working snippet of changing the icon during animation (had to slightly adjust @Croutonix example):

private static final int ANIMATION_DURATION = 300;
private static final float ROTATION_ANGLE = -45f;
private AnimatorSet mOpenAnimatorSet;
private AnimatorSet mCloseAnimatorSet;

private void setUpCustomFabMenuAnimation() {
    mOpenAnimatorSet = new AnimatorSet();
    mCloseAnimatorSet = new AnimatorSet();

    ObjectAnimator collapseAnimator =  ObjectAnimator.ofFloat(mFloatingActionMenu.getMenuIconView(),
                                                              "rotation",
                                                              -90f + ROTATION_ANGLE, 0f);
    ObjectAnimator expandAnimator = ObjectAnimator.ofFloat(mFloatingActionMenu.getMenuIconView(),
                                                           "rotation",
                                                           0f, -90f + ROTATION_ANGLE);

    final Drawable plusDrawable = ContextCompat.getDrawable(MainActivity.this,
                                                            R.drawable.ic_add_black_24dp);
    expandAnimator.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            mFloatingActionMenu.getMenuIconView().setImageDrawable(plusDrawable);
            mFloatingActionMenu.setIconToggleAnimatorSet(mCloseAnimatorSet);
        }
    });

    final Drawable mapDrawable = ContextCompat.getDrawable(MainActivity.this,
                                                           R.drawable.ic_map_black_24dp_png);
    collapseAnimator.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            mFloatingActionMenu.getMenuIconView().setImageDrawable(mapDrawable);
            mFloatingActionMenu.setIconToggleAnimatorSet(mOpenAnimatorSet);
        }
    });

    mOpenAnimatorSet.play(expandAnimator);
    mCloseAnimatorSet.play(collapseAnimator);

    mOpenAnimatorSet.setDuration(ANIMATION_DURATION);
    mCloseAnimatorSet.setDuration(ANIMATION_DURATION);

    mFloatingActionMenu.setIconToggleAnimatorSet(mOpenAnimatorSet);
}
arunavo4 commented 6 years ago

I would like to make the same change in the library itself can you create a pull request so that i can make the same changes