To avoid repetitive code, you can subclass the AnimatorListenerAdapter and create your own AnimatorListener class where you re-attach the view after the animation, then use it wherever needed instead of the default AnimatorListener.
The class:
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
public class PersistViewAnimatorListener extends AnimatorListenerAdapter {
private View view; // keep a reference to the view
public PersistViewAnimatorListener(View view) {
this.view = view;
}
@Override public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
// re-attach the view to its parent at its new location
if (view == null) { return; } // defensive, the view may have been removed while it was animated, do nothing in this case
ViewGroup parent = (ViewGroup) view.getParent(); // get the parent
if (parent == null) { return; } // defensive
int index = parent.indexOfChild(view); // get the index of the view
parent.removeView(view); // remove the view
if (parent.getClass().equals(RelativeLayout.class)) { // RELATIVE LAYOUT
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(view.getLayoutParams()); // add the view back at its index with new layout parameters
layoutParams.setMargins(Math.round(view.getX()), Math.round(view.getY()), 0, 0); // left, top, right, bottom; round the float to int
parent.addView(view, index, layoutParams);
} else if (parent.getClass().equals(FrameLayout.class)) { // FRAME LAYOUT
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(view.getLayoutParams()); // the same for FrameLayout
layoutParams.setMargins(Math.round(view.getX()), Math.round(view.getY()), 0, 0);
parent.addView(view, index, layoutParams);
} else { // currently no further layouts supported, implement these here
throw new UnsupportedOperationException("PersistViewAnimatorListener is currently only supported where the parent is either RelativeLayout or FrameLayout.");
}
view.setTranslationX(0); view.setTranslationY(0); // reset translated values from the animation
}
}
And how you use it:
view.animate().yBy(height).setListener(new PersistViewAnimatorListener(view)); // call your custom listener in .setListener() and pass in the view
This solution assumes you are using RelativeLayout or FrameLayout for the parent. Also, it just cares about the position, not size or other properties that can be animated as well.