Anonymous
Anonymous

Reputation: 962

Android: Animate FAB on tab change

I have a got an Android app with a tabbed activity. Now I want to change the icon of the floating action button if I switch the tab. It should look like in the Material Design Guidelines:

FAB in tabbed activity

I'm not using the FAB from the support library but this one because I also need the FAB menu:

Github

I reviewed the source code and found out that it basically uses an image button for the shape of the FAB and another image button for the icon. By using a scale animation I already managed to create the shrink and scale animation of the button itself:

ScaleAnimation shrink =  new ScaleAnimation(1f, 0.2f, 1f, 0.2f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
shrink.setDuration(150);
shrink.setInterpolator(new DecelerateInterpolator());
shrink.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {}
    @Override
    public void onAnimationRepeat(Animation animation) {}

    @Override
    public void onAnimationEnd(Animation animation) {

        ScaleAnimation expand =  new ScaleAnimation(0.2f, 1f, 0.2f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        expand.setDuration(150);
        expand.setInterpolator(new AccelerateInterpolator());
        animBtn.startAnimation(expand);
    }
});

animBtn.startAnimation(shrink);

Now I'm wondering how I can create an 'uncover' (I don't now how to call it) animation like in the guideline. I don't want to create multiple images of the icon for each frame. Here is what I thought of yet:

I couldn't find a solution for the first one. The second one might be possible but I think there has to be a better solution. The third one doesn't suffice.

Can someone help me, please?

EDIT: I have found a first approach. See my answer below.

EDIT 2: I have improved my approach. Now it looks quite similar to the animation from the guidelines. See my edited answer below, please. What do you think?

Upvotes: 0

Views: 1227

Answers (1)

Anonymous
Anonymous

Reputation: 962

OK, I got pretty close now. After watching the video in slow motion, I think there is also a rotation besides the scaling. Thanks to cYrixmorten, I have got this, now:

ScaleAnimation btnAnim =  new ScaleAnimation (1f, 0.1f, 1f, 0.1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    btnAnim.setDuration(150);
    btnAnim.setInterpolator(new DecelerateInterpolator());
    btnAnim.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {}
        @Override
        public void onAnimationRepeat(Animation animation) {}

        @Override
        public void onAnimationEnd(Animation animation) {

            ScaleAnimation expand =  new ScaleAnimation(0.1f, 1f, 0.1f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
            expand.setDuration(150);
            expand.setInterpolator(new AccelerateInterpolator());
            animBtn.startAnimation(expand);
        }
    });

    ScaleAnimation iconAnim =  new ScaleAnimation(1f, 0.1f, 1f, 0.1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    iconAnim.setDuration(150);
    iconAnim.setInterpolator(new DecelerateInterpolator());
    iconAnim.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {}
        @Override
        public void onAnimationRepeat(Animation animation) {}

        @Override
        public void onAnimationEnd(Animation animation) {
            animIcon.setImageResource(fabIconIntArray[position]);

            Animation expand = new Animation() {
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) {
                    animIcon.setScaleX(0.1f + 0.9f * interpolatedTime);
                    animIcon.setScaleY(0.1f + 0.9f * interpolatedTime);
                    animIcon.setRotation(-20f + interpolatedTime * 20);
                    animIcon.setAlpha(0.5f + 0.5f * interpolatedTime);
                }
            };
            expand.setDuration(150);
            expand.setStartOffset(100);
            expand.setInterpolator(new AccelerateInterpolator());
            animIcon.startAnimation(expand);
        }
    });

    animBtn.startAnimation(btnAnim);
    animIcon.startAnimation(iconAnim);

It looks like this.

I've tried many variants but I think it looks smoother in the guidelines somehow. Does anyone have a suggestion on how I can improve it?

EDIT: After analyzing the video from the guidelines pretty thoroughly, I was able to improve my animation:

ScaleAnimation btnAnim =  new ScaleAnimation(1f, 0f, 1f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
btnAnim.setDuration(250);
btnAnim.setInterpolator(new AccelerateInterpolator());
btnAnim.setAnimationListener(new Animation.AnimationListener() {
     @Override
     public void onAnimationStart(Animation animation) {}
     @Override
     public void onAnimationRepeat(Animation animation) {}

     @Override
     public void onAnimationEnd(Animation animation) {

          ScaleAnimation expand =  new ScaleAnimation(0f, 1f, 0f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
          expand.setDuration(195);
          expand.setInterpolator(new DecelerateInterpolator());
          animBtn.startAnimation(expand);
     }
});

ScaleAnimation iconAnim =  new ScaleAnimation(1f, 0f, 1f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
iconAnim.setDuration(250);
iconAnim.setInterpolator(new AccelerateInterpolator());
iconAnim.setAnimationListener(new Animation.AnimationListener() {
     @Override
     public void onAnimationStart(Animation animation) {}
     @Override
     public void onAnimationRepeat(Animation animation) {}

     @Override
     public void onAnimationEnd(Animation animation) {
          animIcon.setImageResource(fabIconIntArray[position]);
          Animation expand = new Animation() {
               @Override
               protected void applyTransformation(float interpolatedTime, Transformation t) {
                    animIcon.setScaleX(interpolatedTime);
                    animIcon.setScaleY(interpolatedTime);
                    animIcon.setRotation(-20f + interpolatedTime * 20);
               }
          };
          expand.setStartOffset(135);
          expand.setDuration(215);
          expand.setInterpolator(new DecelerateInterpolator());
          animIcon.startAnimation(expand);
     }
});

animBtn.startAnimation(btnAnim);
animIcon.startAnimation(iconAnim);

Now it looks like this. What do you think?

Upvotes: 1

Related Questions