Reputation: 28509
Here's the animation:
public class WidthAnimation extends Animation {
protected final int originalWidth;
protected final View view;
protected float perValue;
public WidthAnimation(View view, int fromWidth, int toWidth) {
this.view = view;
this.originalWidth = fromWidth;
this.perValue = (toWidth - fromWidth);
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
view.getLayoutParams().width = (int) (originalWidth + perValue * interpolatedTime);
view.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
}
When called by this (animating the View to be zero width), it works fine:
WidthAnimation widthAnim = new WidthAnimation(dashboardContainerView, getWindowWidthInPixels(), 0);
widthAnim.setDuration(500);
dashboardContainerView.startAnimation(widthAnim);
But when called by this (animating the View to being displayed), applyTransform is not called, and the animation is not shown:
WidthAnimation widthAnim = new WidthAnimation(dashboardContainerView, 0, getWindowWidthInPixels());
widthAnim.setDuration(500);
dashboardContainerView.startAnimation(widthAnim);
Both animations are being triggered by screen clicks. The getWindowWidthInPixels() method works correctly. I've seen several other questions on SO that suggest calling invalidate() or requestLayout() on the View, or its parent, can resolve this, but for me those solutions do not work.
Upvotes: 0
Views: 3669
Reputation: 2377
Wow, that is weird, that it would work to shrink but not grow. Maybe Android is discarding the startAnimation call because the view is width 0. I suppose one quick fix would be to set the width to 1 before starting the grow animation.
dashboardContainerView.getLayoutParams().width = 1;
WidthAnimation widthAnim = new WidthAnimation(dashboardContainerView, 0, getWindowWidthInPixels());
widthAnim.setDuration(500);
dashboardContainerView.startAnimation(widthAnim);
Another option would be to switch to ObjectAnimator. My animations got a lot more straightforward when I did that. Yours would look something like this:
ObjectAnimator anim = ObjectAnimator.ofInt(this, "dashboardWidth", fromWidth, toWidth);
anim.setDuration(500);
dashboardContainerView.startAnimation(anim);
public void setDashboardWidth(int width) {
ViewGroup.LayoutParams params = dashboardContainerView.getLayoutParams();
params.width = width;
dashboardContainerView.setLayoutParams(params);
}
That is the pattern I usually use with success. I don't have to call requestLayout in that case, but maybe setLayoutParams is doing that. Maybe just the getLayoutParams and requestLayout that you are using would be fine too.
Anyway, I really like the ObjectAnimator because it is so simple. One thing you do have to watch out for is if you are using ProGuard, you have to make sure it doesn't clean out the setDashboardWidth method, because it is not directly called in your code. It is called from within ObjectAnimator, which finds the method using reflection. Thus the exact name and signature of the method has to match the "dashboardWidth" property name in the call to ofInt.
Upvotes: 2