可視性がに設定されたAnimation
ときのforを作成したいと思います。単に消えるのではなく、「崩壊」する必要があります。これを試してみましたが、は折りたたまれていますが、レイアウトは停止(または開始)後(または開始前)にのみスペースのサイズを変更します。View
GONE
View
ScaleAnimation
View
Animation
Animation
アニメーション化中に、下部View
のsが空白ではなく、コンテンツの真下にとどまるようにするにはどうすればよいですか?
可視性がに設定されたAnimation
ときのforを作成したいと思います。単に消えるのではなく、「崩壊」する必要があります。これを試してみましたが、は折りたたまれていますが、レイアウトは停止(または開始)後(または開始前)にのみスペースのサイズを変更します。View
GONE
View
ScaleAnimation
View
Animation
Animation
アニメーション化中に、下部View
のsが空白ではなく、コンテンツの真下にとどまるようにするにはどうすればよいですか?
回答:
アニメーションは実際のサイズではなく、ビューのレンダリングマトリックスを変更するだけなので、APIを介してこれを行う簡単な方法はないようです。ただし、LinearLayoutをだまして、ビューが小さくなっていると思わせるために、負のマージンを設定することはできます。
したがって、ScaleAnimationに基づいて独自のAnimationクラスを作成し、「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/で機能する完全な例があります
ここではAndyと同じ手法を使用し、グリッチなしで拡張および折りたたみに使用できるように改良しました。また、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();
}
}