Quiero hacer un Animation
para cuando a View
tenga su visibilidad configurada GONE
. En lugar de simplemente desaparecer, View
debería "colapsar". Intenté esto con a, ScaleAnimation
pero luego View
se contrajo, pero el diseño solo cambiará el tamaño de su espacio después (o antes) de las Animation
paradas (o inicios).
¿Cómo puedo hacer Animation
que, durante la animación, las letras inferiores View
queden directamente debajo del contenido, en lugar de tener un espacio en blanco?
Respuestas:
No parece haber una manera fácil de hacer esto a través de la API, porque la animación simplemente cambia la matriz de representación de la vista, no el tamaño real. Pero podemos establecer un margen negativo para engañar a LinearLayout haciéndole pensar que la vista es cada vez más pequeña.
Por lo tanto, recomiendo crear su propia clase de animación, basada en ScaleAnimation, y anular el método "applyTransformation" para establecer nuevos márgenes y actualizar el diseño. Me gusta esto...
public class Q2634073 extends Activity implements OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.q2634073); findViewById(R.id.item1).setOnClickListener(this); } @Override public void onClick(View view) { view.startAnimation(new MyScaler(1.0f, 1.0f, 1.0f, 0.0f, 500, view, true)); } public class MyScaler extends ScaleAnimation { private View mView; private LayoutParams mLayoutParams; private int mMarginBottomFromY, mMarginBottomToY; private boolean mVanishAfter = false; public MyScaler(float fromX, float toX, float fromY, float toY, int duration, View view, boolean vanishAfter) { super(fromX, toX, fromY, toY); setDuration(duration); mView = view; mVanishAfter = vanishAfter; mLayoutParams = (LayoutParams) view.getLayoutParams(); int height = mView.getHeight(); mMarginBottomFromY = (int) (height * fromY) + mLayoutParams.bottomMargin - height; mMarginBottomToY = (int) (0 - ((height * toY) + mLayoutParams.bottomMargin)) - height; } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { super.applyTransformation(interpolatedTime, t); if (interpolatedTime < 1.0f) { int newMarginBottom = mMarginBottomFromY + (int) ((mMarginBottomToY - mMarginBottomFromY) * interpolatedTime); mLayoutParams.setMargins(mLayoutParams.leftMargin, mLayoutParams.topMargin, mLayoutParams.rightMargin, newMarginBottom); mView.getParent().requestLayout(); } else if (mVanishAfter) { mView.setVisibility(View.GONE); } } } }
Se aplica la advertencia habitual: debido a que anulamos un método protegido (applyTransformation), no se garantiza que funcione en futuras versiones de Android.
fuente
0 -
en elmarginBottomToY
cálculo.MarginLayoutParams
lugar de convertirlo en unLayoutParam
tipo específico .Coloque la vista en un diseño si no es así y configúrelo
android:animateLayoutChanges="true"
para ese diseño.fuente
Usé la misma técnica que Andy ha presentado aquí. Escribí mi propia clase de animación para eso, que anima el valor del margen, haciendo que el efecto del elemento desaparezca / aparezca. Se parece a esto:
public class ExpandAnimation extends Animation { // Initializations... @Override protected void applyTransformation(float interpolatedTime, Transformation t) { super.applyTransformation(interpolatedTime, t); if (interpolatedTime < 1.0f) { // Calculating the new bottom margin, and setting it mViewLayoutParams.bottomMargin = mMarginStart + (int) ((mMarginEnd - mMarginStart) * interpolatedTime); // Invalidating the layout, making us seeing the changes we made mAnimatedView.requestLayout(); } } }
Tengo un ejemplo completo que funciona en mi publicación de blog http://udinic.wordpress.com/2011/09/03/expanding-listview-items/
fuente
Usé la misma técnica que Andy aquí y la refiné para que pueda usarse para expandir y colapsar sin fallas, también usando una técnica que se describe aquí: https://stackoverflow.com/a/11426510/1317564
import android.view.View; import android.view.ViewTreeObserver; import android.view.animation.ScaleAnimation; import android.view.animation.Transformation; import android.widget.LinearLayout; class LinearLayoutVerticalScaleAnimation extends ScaleAnimation { private final LinearLayout view; private final LinearLayout.LayoutParams layoutParams; private final float beginY; private final float endY; private final int originalBottomMargin; private int expandedHeight; private boolean marginsInitialized = false; private int marginBottomBegin; private int marginBottomEnd; private ViewTreeObserver.OnPreDrawListener preDrawListener; LinearLayoutVerticalScaleAnimation(float beginY, float endY, LinearLayout linearLayout) { super(1f, 1f, beginY, endY); this.view = linearLayout; this.layoutParams = (LinearLayout.LayoutParams) linearLayout.getLayoutParams(); this.beginY = beginY; this.endY = endY; this.originalBottomMargin = layoutParams.bottomMargin; if (view.getHeight() != 0) { expandedHeight = view.getHeight(); initializeMargins(); } } private void initializeMargins() { final int beginHeight = (int) (expandedHeight * beginY); final int endHeight = (int) (expandedHeight * endY); marginBottomBegin = beginHeight + originalBottomMargin - expandedHeight; marginBottomEnd = endHeight + originalBottomMargin - expandedHeight; marginsInitialized = true; } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { super.applyTransformation(interpolatedTime, t); if (!marginsInitialized && preDrawListener == null) { // To avoid glitches, don't draw until we've initialized everything. preDrawListener = new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { if (view.getHeight() != 0) { expandedHeight = view.getHeight(); initializeMargins(); adjustViewBounds(0f); view.getViewTreeObserver().removeOnPreDrawListener(this); } return false; } }; view.getViewTreeObserver().addOnPreDrawListener(preDrawListener); } if (interpolatedTime < 1.0f && view.getVisibility() != View.VISIBLE) { view.setVisibility(View.VISIBLE); } if (marginsInitialized) { if (interpolatedTime < 1.0f) { adjustViewBounds(interpolatedTime); } else if (endY <= 0f && view.getVisibility() != View.GONE) { view.setVisibility(View.GONE); } } } private void adjustViewBounds(float interpolatedTime) { layoutParams.bottomMargin = marginBottomBegin + (int) ((marginBottomEnd - marginBottomBegin) * interpolatedTime); view.getParent().requestLayout(); } }
fuente