Android - Change left margin using animation
AndroidAndroid AnimationAndroid 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.