Android - Change left margin using animation

AndroidAndroid Animation

Android Problem Overview


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;

Android Solutions


Solution 1 - Android

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

Solution 2 - Android

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.

Solution 3 - Android

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.

Solution 4 - Android

Nothing worked for me like I wanted so... I needed to create ToggleMenu from -80 dp (oldLeftMargin) to 0dp. Same with bottomMargin, etc. Now it works:

final int oldLeftMargin = (int) getResources().getDimension(R.dimen.left_menu_button_margin_left);
    Animation a = new Animation() {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) llMeniuToggle.getLayoutParams();
            params.leftMargin = oldLeftMargin + (int) ((0 - oldLeftMargin) * interpolatedTime);
            llMeniuToggle.setLayoutParams(params);
        }
    };
    a.setDuration(500);
    llMeniuToggle.startAnimation(a);

Solution 5 - Android

You can use the following

image.animate().setDuration(durationIn).translationXBy(offsetFloat).start();

You can also add .setInterpolator(new BounceInterpolator()) to change the look of the animation.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLeeeeeeeloView Question on Stackoverflow
Solution 1 - Androiduser1991679View Answer on Stackoverflow
Solution 2 - AndroidAliView Answer on Stackoverflow
Solution 3 - AndroidBjörn KechelView Answer on Stackoverflow
Solution 4 - AndroidMarinaView Answer on Stackoverflow
Solution 5 - AndroidAleksei TView Answer on Stackoverflow