Android ResizeAnimation with a starting height

Posted by – December 13, 2011

I recently found a a way to resize a view in a way to make it open/collaspse in a Android activity, this kind of animation gives some charm when showing some interface elements like a toolbar or a navigator to the user, you can make it show on screen completelly or have a small piece visible and disclose all the hidden portion.

This animation is based on some code that can be found on stackoverlow, but I made few changes to add extra features to it like start the animation from specific height instead of 0.

Here’s the full code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package br.com.lgkaiser.sgpoffline.activity.animation;

import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;

public class ResizeAnimation extends Animation {

    int originalHeight;
    int targetHeight;
    int offsetHeight;
    int adjacentHeightIncrement;
    View view, adjacentView;
    boolean down;

    //This constructor makes the animation start from height 0px
    public ResizeAnimation(View view, int offsetHeight, boolean down) {
        this.view           = view;
        this.originalHeight = 0;
        this.targetHeight   = 0;
        this.offsetHeight   = offsetHeight;
        this.down           = down;
    }
   
    //This constructor allow us to set a starting height
    public ResizeAnimation(View view, int originalHeight, int targetHeight, boolean down) {
        this.view           = view;
        this.originalHeight = originalHeight;
        this.targetHeight   = targetHeight;
        this.offsetHeight   = targetHeight - originalHeight;
        this.down           = down;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        int newHeight;
        if (down)
            newHeight = (int) (offsetHeight * interpolatedTime);
       
        else
            newHeight = (int) (offsetHeight * (1 - interpolatedTime));
       
        //The new view height is based on start height plus the height increment
        view.getLayoutParams().height = newHeight + originalHeight;
        view.requestLayout();
       
        if (adjacentView != null) {
                        //This line is only triggered to animate and adjacent view
            adjacentView.getLayoutParams().height = view.getLayoutParams().height + adjacentHeightIncrement;
            adjacentView.requestLayout();
        }
    }

    @Override
    public void initialize(int width, int height, int parentWidth,
            int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
    }

    @Override
    public boolean willChangeBounds() {
        return true;
    }
   
    public void setAdjacentView(View adjacentView) {
        this.adjacentView = adjacentView;
    }
   
    public void setAdjacentHeightIncrement(int adjacentHeightIncrement) {
        this.adjacentHeightIncrement = adjacentHeightIncrement;
    }
}

To trigger the animation you can use the following piece of code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ResizeAnimation animation = null;
animation = new ResizeAnimation(yourView, 57, 157, false);
//1 second is enougth for animation duration run smoothly
animation.setDuration(1000);
animation.setAnimationListener(new Animation.AnimationListener() {
   
    @Override
    public void onAnimationStart(Animation animation) {
       
    }
   
    @Override
    public void onAnimationRepeat(Animation animation) {

    }
   
    @Override
    public void onAnimationEnd(Animation animation) {

    }
});
yourView.startAnimation(animation);

Now you are ready to animate your views with some more elegance.

Share

1 Comment on Android ResizeAnimation with a starting height

  1. Sean Wallis says:

    A more elegant algorithm is to get the start height from the view and the height from start+diff*interpolated time, where diff = end height – start height.

    Leaving out animation of adjacent elements this gives us:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    public class ResizeAnimation extends Animation
    {
        View view;
        int startH;
        int endH;
        int diff;

        public ResizeAnimation(View v, int newh)
        {
            view = v;
            startH = v.getLayoutParams().height;
            endH = newh;
            diff = endH - startH;
        }
           
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t)
        {
            view.getLayoutParams().height = startH + (int)(diff*interpolatedTime);
            view.requestLayout();
        }

        @Override
        public void initialize(int width, int height, int parentWidth, int parentHeight)
        {
            super.initialize(width, height, parentWidth, parentHeight);
        }

        @Override
        public boolean willChangeBounds()
        {
            return true;
        }
    }

    However my final observation is that resizing is not as slick as hardware animations like TranslateAnimation. So if you are using this to reveal an element you are likely to get a better result with TranslateAnimation, particularly on lesser devices.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>