Android - Change left margin using animation

2019-01-16 11:32发布

问题:

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;

回答1:

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



回答2:

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.



回答3:

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.



回答4:

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.