19

I need to change the width of a RelativeLayout from 0 to 600px programmatically, in an animated way. I'm using the following code:

Animation a = new Animation() {
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        RelativeLayout.LayoutParams drawerParams = (LayoutParams) drawer.getLayoutParams();
        drawerParams.width = 600;
        drawer.setLayoutParams(drawerParams);
    }
};

a.setDuration(1000); //Animate for 1s
layout.startAnimation(a);

However, for some reason this isn't working. Can anyone point me in the right direction?

Wakka02
  • 1,491
  • 4
  • 28
  • 44

4 Answers4

54

I just typed this up and works perfect here

Animation

public class ResizeWidthAnimation extends Animation {
    private int mWidth;
    private int mStartWidth;
    private View mView;
    
    public ResizeWidthAnimation(View view, int width) {
        mView = view;
        mWidth = width;
        mStartWidth = view.getWidth();
    }
    
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        int newWidth = mStartWidth + (int) ((mWidth - mStartWidth) * interpolatedTime);

        mView.getLayoutParams().width = newWidth;
        mView.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;
    }
}

usage

if (animate) {
    ResizeWidthAnimation anim = new ResizeWidthAnimation(leftFrame, leftFragmentWidthPx);
    anim.setDuration(500);
    leftFrame.startAnimation(anim);
} else {
    this.leftFragmentWidthPx = leftFragmentWidthPx;
    LayoutParams lp = (LayoutParams) leftFrame.getLayoutParams();
    lp.width = leftFragmentWidthPx;
    leftFrame.setLayoutParams(lp);
}

UPDATE: Kotlin Version

class ResizeWidthAnimation(private val mView: View, private val mWidth: Int) : Animation() {
    private val mStartWidth: Int = mView.width

    override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
        mView.layoutParams.width = mStartWidth + ((mWidth - mStartWidth) * interpolatedTime).toInt()
        mView.requestLayout()
    }

    override fun willChangeBounds(): Boolean {
        return true
    }
}
theapache64
  • 10,926
  • 9
  • 65
  • 108
Saren Inden
  • 3,450
  • 4
  • 32
  • 45
  • 1
    Is it just me or changing duration has no effect? – Zyoo Apr 14 '15 at 02:39
  • It some times work sometimes does not. Is it just me :) – Karacago Sep 27 '15 at 08:00
  • Always in the same layout? It might work different in linear vs relative layout, i'am not really sure either, it is pretty old code by now and haven't used it myself in a while either. – Saren Inden Sep 29 '15 at 10:25
  • 2
    It could be better if you would mention some value of animate, leftframe and leftframewidthpx – Irfan Raza Oct 31 '16 at 13:41
  • Look at the implementation of the animation object. It expects a view (you want to animate a view, so that should probably be the view you provide) and you want to change the width (is of type int) so make it 300 and your view will become 300 width. – Saren Inden Oct 31 '16 at 13:52
  • what is the function of this if statement? if(animate) how and when the value of this animate variable will be changed? can you please guide me – User Mar 15 '17 at 04:48
  • Simply part of a function that layouts the the items animated or not. 'public void layoutComponent(boolean animated) { .... } – Saren Inden Mar 15 '17 at 13:16
4

A lot of times the easiest way to animate layout changes in Android is to set the animateLayoutChanges attribute to true in the layout xml. For more details, see http://developer.android.com/training/animation/layout.html.

emidander
  • 2,383
  • 22
  • 29
0

Instead of setLayoutParams(), call requestLayout() after the width change.

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • Do I do this outside of the applyTransformation method or inside? – Wakka02 May 20 '13 at 02:15
  • of course it dosn`t works... this is how to set layout sizes. int newWidth = originalWidth + (int) ((this.newWidth - originalWidth) * interpolatedTime); LinearLayout.LayoutParams parms = new LinearLayout.LayoutParams(newWidth, this.newHeight); mView.setLayoutParams(parms); mView.requestLayout(); – narancs Mar 16 '15 at 22:49
  • Calling `setLayoutParams()` is enough. It calls `requestLayout()` at the end. – WindRider Dec 01 '15 at 12:40
0

This is what worked for me:

public class CloseImageFromRightToLeft extends Animation {
    private final int newWidth;
    private final int newHeight;
    private final int originalWidth;
    private ImageView mView;

    public CloseImageFromRightToLeft(ImageView v, int[] widthAndHeight) {
        mView = v;
        this.newWidth = widthAndHeight[0] / 3;
        this.originalWidth = widthAndHeight[0];
        this.newHeight = widthAndHeight[1];
    }

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

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

    @Override
    public void applyTransformation(float interpolatedTime, Transformation t) {
        int newWidth = originalWidth + (int) ((this.newWidth - originalWidth) * interpolatedTime);


        LinearLayout.LayoutParams parms = new LinearLayout.LayoutParams(newWidth, this.newHeight);
        mView.setLayoutParams(parms);
        mView.requestLayout();
    }
}
Tash Pemhiwa
  • 7,590
  • 4
  • 45
  • 49
narancs
  • 5,234
  • 4
  • 41
  • 60