Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - Change left margin using animation

I am changing the left margin of an image view in the following manner :

ViewGroup.MarginLayoutParams layoutParams = (MarginLayoutParams) image.getLayoutParams ();
layoutParams.leftMargin = VALUE;
image.setLayoutParams ( layoutParams );

I would like the change in margin to apply with animation. Any clues ?

What I tried :

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat ( image , "x" , VALUE);
objectAnimator.start();

This works perfectly, as the image is moved to the specified X value with animation, HOWEVER the value of layoutParams.leftMargin remains unchanged !! So I cannot use this method, because if I try to change the value of layoutParams.leftMargin to 100 after using the objectAnimator with the value 100, the value applied is not correct ( 200 is applied instead of 100, the effect if the objectAnimator remains eventhough I am setting the left margin in the following manner :

layoutParams.leftMargin = 100;
like image 782
Leeeeeeelo Avatar asked Dec 14 '12 15:12

Leeeeeeelo


3 Answers

Use Animation class, not ObjectAnimator.

final int newLeftMargin = <some value>;
Animation a = new Animation() {

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        LayoutParams params = yourView.getLayoutParams();
        params.leftMargin = (int)(newLeftMargin * interpolatedTime);
        yourView.setLayoutParams(params);
    }
};
a.setDuration(500); // in ms
yourView.startAnimation(a);

Please note that you should use correct LayoutParams class i.e. if your view is the child of LinearLayout then params should be LinearLayout.LayoutParams

like image 174
user1991679 Avatar answered Nov 15 '22 05:11

user1991679


I came by this question, but I couldn't use it because I want to animate the margin from a negative value to 0, so I used valueAnimater base on user1991679 answer:

final View animatedView = view.findViewById(R.id.animatedView);
final LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) animatedView.getLayoutParams();
ValueAnimator animator = ValueAnimator.ofInt(params.bottomMargin, 0);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator)
    {
        params.bottomMargin = (Integer) valueAnimator.getAnimatedValue();
        animatedView.requestLayout();
    }
});
animator.setDuration(300);
animator.start();

You must change LinearLayout.LayoutParams according to animatedView container. Also you can use nineoldandroids for older version that don't have ValueAnimator.

like image 41
Ali Avatar answered Nov 15 '22 05:11

Ali


The answer from user1991679 is great, but if you need to interpolate a margin from any other value but 0, you need to use it in your calculations:

ViewGroup.MarginLayoutParams params = (MarginLayoutParams) mBottomLayout.getLayoutParams();
final int bottomMarginStart = params.bottomMargin; // your start value
final int bottomMarginEnd = <your value>; // where to animate to
Animation a = new Animation() {
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        ViewGroup.MarginLayoutParams params = (MarginLayoutParams) mBottomLayout.getLayoutParams();
        // interpolate the proper value
        params.bottomMargin = bottomMarginStart + (int) ((bottomMarginEnd - bottomMarginStart) * interpolatedTime);
        mBottomLayout.setLayoutParams(params);
    }
};
a.setDuration(300);
mBottomLayout.startAnimation(a);

In my case I needed to animate an "enter the screen" animation, coming from "-48dp" to 0. Without the start value, the animation is always 0, thus jumping, not animating the view. The solution was to interpolate the offset and add it to the original value.

like image 17
Björn Kechel Avatar answered Nov 15 '22 06:11

Björn Kechel