Я хочу сделать, Animation
когда для View
него будет установлена видимость GONE
. Вместо того, чтобы просто исчезнуть, он View
должен «рухнуть». Я пробовал это с помощью, ScaleAnimation
но затем View
происходит коллапс, но макет изменяет размер только после (или до) Animation
остановок (или запусков).
Как я могу сделать Animation
так, чтобы во время анимации нижние View
s оставались прямо под содержимым, вместо того, чтобы иметь пустое пространство?
Ответы:
Кажется, не существует простого способа сделать это через API, потому что анимация просто изменяет матрицу рендеринга представления, а не фактический размер. Но мы можем установить отрицательное поле, чтобы заставить LinearLayout думать, что представление становится меньше.
Поэтому я бы рекомендовал создать свой собственный класс анимации на основе ScaleAnimation и переопределить метод «applyTransformation», чтобы установить новые поля и обновить макет. Как это...
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); } } } }
Применяется обычное предостережение: поскольку мы переопределяем защищенный метод (applyTransformation), это не гарантирует работу в будущих версиях Android.
источник
0 -
вmarginBottomToY
расчетах.MarginLayoutParams
вместо того, чтобы приводить его к определенномуLayoutParam
типу.Поместите вид в макет, если это не так, и установите его
android:animateLayoutChanges="true"
для этого макета.источник
Я использовал ту же технику, что и Энди. Я написал для этого свой собственный класс Animation, который анимирует значение поля, вызывая исчезновение / появление эффекта элемента. Выглядит это так:
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(); } } }
У меня есть полный пример, который работает в моем сообщении в блоге http://udinic.wordpress.com/2011/09/03/expanding-listview-items/
источник
Здесь я использовал ту же технику, что и Энди, и усовершенствовал ее, чтобы ее можно было использовать для расширения и свертывания без сбоев, также используя метод, описанный здесь: 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(); } }
источник