Android: agrega vista con expandir animación (sin parpadear)

Quiero agregar una vista a un grupo de vistas mediante una animación en expansión, por lo que la vista agregada comienza muy pequeña y ocupa más espacio hasta que alcanza su tamaño completo (probablemente, mover otras vistas en el proceso).

Después de probar diferentes enfoques, se me ocurrió la solución a continuación. Vota si te ayuda o por favor publica una mejor alternativa. Estoy seguro de que debe haber una manera más fácil de hacer esto.

Para más información ver publicaciones comoéste yéste.

Así es como agrego la vista y comienzo la animación:

// Trick: set height to 1 so the view doesn't take its full size at the beginning.
// (0 doesn't work, I don't know why)
container.addView(view, LayoutParams.MATCH_PARENT, 1);
Animation expansion = createExpansion(view);
expansion.setDuration(200);
view.startAnimation(expansion);

loscreateExpansion() método:

public static Animation createExpansion(View view) {

    return new SizedHeightScaleAnimation(view, 0, 1,
            Animation.RELATIVE_TO_SELF, 0f,
            Animation.RELATIVE_TO_SELF, 0f);
}

Y finalmente elSizedHeightScaleAnimation clase de animacion

/**
 * Like {@link ScaleAnimation} for height scaling that also resizes the view accordingly,
 * so it takes the right amount of space while scaling.
 */
public class SizedHeightScaleAnimation extends ScaleAnimation {

    private float fromHeight;
    private float toHeight;
    private View viewToScale;

    public SizedHeightScaleAnimation(View viewToScale, float fromY, float toY) {
        super(1, 1, fromY, toY);
        init(viewToScale, fromY, toY);
    }

    public SizedHeightScaleAnimation(View viewToScale, float fromY, float toY, float pivotX, float pivotY) {
        super(1, 1, fromY, toY, pivotX, pivotY);
        init(viewToScale, fromY, toY);
    }

    public SizedHeightScaleAnimation(View viewToScale, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {
        super(1, 1, fromY, toY, pivotXType, pivotXValue, pivotYType, pivotYValue);
        init(viewToScale, fromY, toY);
    }

    private void init(View viewToScale, float fromY, float toY) {

        this.viewToScale = viewToScale;
        viewToScale.measure(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        fromHeight = viewToScale.getMeasuredHeight() * fromY;
        toHeight = viewToScale.getMeasuredHeight() * toY;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);

        final int newHeight = (int) (fromHeight * (1 - interpolatedTime) + toHeight * interpolatedTime);

        viewToScale.getLayoutParams().height = newHeight;
        viewToScale.requestLayout();
    }
}

Por cierto, puedes crear el efecto de colapso de esta manera:

public static Animation createCollapse(View view) {

    return new SizedHeightScaleAnimation(view, 1, 0,
            Animation.RELATIVE_TO_SELF, 0f,
            Animation.RELATIVE_TO_SELF, 0f);
}

Cuando lo uses, probablemente querrás quitar la vista de su padre cuando la animación haya terminado:

Animation collapse = createCollapse(view);
collapse.setDuration(200);

collapse.setAnimationListener(new AnimationListener() {
    @Override
    public void onAnimationEnd(Animation animation) {
        final ViewGroup parent = (ViewGroup) view.getParent();
        parent.removeView(view);
    }

    ... other overrides ...
});

view.startAnimation(collapse);

Respuestas a la pregunta(1)

Su respuesta a la pregunta