ポイントからフェースへ、Buttonのアトリビュートをアニメートするには
12660 ワード
属性アニメーションはAPI 11に追加された新しい特性であり、実際には今でも新しいものはありません.属性アニメーションは任意のviewの属性をアニメーション化することができ、アニメーションを実現する原理は、与えられた時間内に属性を1つの値から別の値に変えることである.そのため、viewにこの属性があれば、属性アニメーションは何でもできると言えます.
ここでは
だからどうしてもアトリビュートアニメーションを使います.ここでは最も簡単な方法:
簡単に見えるボタンのアニメーションが実現しました.しかし、運転中に問題が発生します.なぜなら、属性アニメーションは実行時に指定された属性を変更する必要があるため、ここでは
しかし、
この場合、Googleは3つの解決方法を提供しました.あなたのviewにgetとsetメソッドを追加します.しかし、これはあなたにこの権限が必要です. は、ターゲットviewをクラスでパッケージし、getメソッドとsetメソッドを間接的にこのviewに追加する. は、
この方法は簡単に見えますが、クラスを間接的にget、setを与える方法を定義すると、次のようになります.アニメーションがlayout paramsの幅を変更する必要がある以上、このsetメソッドではlayout paramsの幅を変更します. はlayout paramsの幅を返します.この値はviewのアニメーション前の幅です.
ボタンをクリックして、この幅を修正するアニメーションを開始します.は包装類でviewを包装しています.ここはボタンです. はアニメーションを開始し、アニメーションのオブジェクトはパッケージクラスオブジェクトになります.ここでは、アトリビュートアニメーションの定義を変更できます.アトリビュートアニメーションは、任意のオブジェクトに対してアトリビュートを変更できます.ここでのパッケージオブジェクトは明らかにviewではありません. ここにリスナーが追加され、アニメーションのリスニングが開始されたか終了したかが表示されます. アニメーションを開始します.ボタンの幅を3秒で変更し、初期値から1500ピクセル幅に変更します.
完璧に見えますが、このセグメントコードを実行します.ボタンをクリックします.まあ、このアニメーションはおかしくて、「完全」を実行していません.少し動いたが、幅1500ピクセルには達しなかった.アニメーションリスナー
では、これはなぜですか.まず正しいコードを与えて、皆さんは参考にして考えてみてください.パッケージクラスオブジェクトクラスメンバーを宣言します. は、
これにより、一度にアニメーションを指定した幅にすることができます.具体的にはなぜですか?また后ろのコメントで一绪に讨论することを歓迎します.;)
これは簡単です.コードを直接見てください.は の第3のステップのアルゴリズムは、現在のアニメーションがアニメーション時間全体に占めるタイムスライスの割合を取得することであり、ここでは
完全なコードはここを見てください.ここまで全部説明します.レンガを撮ることを歓迎して、討論を歓迎します!
ここでは
Button
について簡単なプロパティアニメーションを行います.このButton
の幅を変更します.Tween Animation
も使えますが、明らかに要求を満たすことができないところはTween Animation
でScaleアニメーション、つまりスケールしかできません.このbuttonをズームして幅を大きくすることができますが、このときボタンの文字もズームや変形します.同時に重要なのは、Tween Animation
がviewの本来の位置と大きさを変えないことです.このボタンは大きくなっているように見えますが、アニメーション実行前のボタンをクリックしても上書きされていない位置は効果がありません.だからどうしてもアトリビュートアニメーションを使います.ここでは最も簡単な方法:
ObjectAnimator
を使用してこのアニメーションを作成します.ObjectAnimator.ofInt(mAnimateButton, "width", mAnimateButton.getWidth(), 1000)
.setDuration(1000)
.start();
簡単に見えるボタンのアニメーションが実現しました.しかし、運転中に問題が発生します.なぜなら、属性アニメーションは実行時に指定された属性を変更する必要があるため、ここでは
width
の値である.属性に対応するgetWidth
とsetWidth
のメソッドを使用します.getWidth
は、アニメーションの初期値が与えられていない場合に、この方法を用いて初期値を得る.setWidth
は、所与の時間内に、アニメーションの効果を達成するために属性値を変更するために絶えず使用される.注意、この方法は一度だけではありません.しかし、
Button
のgetWidth
とsetWidth
の2つの方法のコードを見てみましょう. /**
* Return the width of the your view.
*
* @return The width of your view, in pixels.
*/
@ViewDebug.ExportedProperty(category = "layout")
public final int getWidth() {
return mRight - mLeft;
}
/**
* Makes the TextView exactly this many pixels wide.
* You could do the same thing by specifying this number in the
* LayoutParams.
*
* @see #setMaxWidth(int)
* @see #setMinWidth(int)
* @see #getMinWidth()
* @see #getMaxWidth()
*
* @attr ref android.R.styleable#TextView_width
*/
@android.view.RemotableViewMethod
public void setWidth(int pixels) {
mMaxWidth = mMinWidth = pixels;
mMaxWidthMode = mMinWidthMode = PIXELS;
requestLayout();
invalidate();
}
setWidth
の場合、ボタンlayout paramの幅を所定の値で変更しなかったことは明らかである.この場合、Googleは3つの解決方法を提供しました.
ValueAnimator
とAnimatorUpdateListener
でアニメーションをリスニングし、各タイムスライスのプロパティを自分で変更します.Button
にgetとsetを追加する方法は現実的ではないので、後の2つしか選択できません.次の2つの方法を紹介します.間接的にget、setメソッドを与える
この方法は簡単に見えますが、クラスを間接的にget、setを与える方法を定義すると、次のようになります.
class ViewWrapper {
View mTargetView;
public ViewWrapper(View v) {
mTargetView = v;
}
public void setWidth(int width) {
mTargetView.getLayoutParams().width = width; // 1
mTargetView.requestLayout();
}
public int getWidth() {
int width = mTargetView.getLayoutParams().width; // 2
return width;
}
}
ボタンをクリックして、この幅を修正するアニメーションを開始します.
@Override
public void onClick(View v) {
Log.d("##ViewWrapperActivity", "width is " + v.getWidth());
// 1
ViewWrapper viewWrapper = new ViewWrapper(v);
// 2
ObjectAnimator animator = ObjectAnimator.ofInt(viewWrapper, "width", /*viewWrapper.getWidth(),*/ 1500);
// 3
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
Log.d("##ANIM", "started");
}
@Override
public void onAnimationEnd(Animator animation) {
Log.d("##ANIM", "stopped");
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
// 4
animator.setDuration(3000).start();
}
完璧に見えますが、このセグメントコードを実行します.ボタンをクリックします.まあ、このアニメーションはおかしくて、「完全」を実行していません.少し動いたが、幅1500ピクセルには達しなかった.アニメーションリスナー
AnimatorListener
のメソッドonAnimationEnd
は既に実行されており、実行完了のロゴも掲げられているが、幅は常に届かない.したがって、アニメーションの実行は「完全」ではありません.では、これはなぜですか.まず正しいコードを与えて、皆さんは参考にして考えてみてください.
public class ViewWrapperActivity extends Activity implements View.OnClickListener {
private Button mAnimateButton;
// 1
private ViewWrapper mWrapper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_wrapper);
mAnimateButton = (Button) findViewById(R.id.animate_button);
mAnimateButton.setOnClickListener(this);
// 2
mWrapper = new ViewWrapper(mAnimateButton);
}
@Override
public void onClick(View v) {
Log.d("##ViewWrapperActivity", "width is " + v.getWidth());
ObjectAnimator animator = ObjectAnimator.ofInt(mWrapper, "width", /*viewWrapper.getWidth(),*/ 1500);
animator.setInterpolator(new LinearInterpolator());
animator.addListener(new Animator.AnimatorListener() {
// ...
});
animator.setDuration(3000).start();
}
}
onCreate
の方法でパッケージクラスオブジェクトを初期化する.これにより、一度にアニメーションを指定した幅にすることができます.具体的にはなぜですか?また后ろのコメントで一绪に讨论することを歓迎します.;)
ValueAnimatorとAnimatorUpdateListenerの組み合わせでアニメーションを実現
これは簡単です.コードを直接見てください.
private void performAnimation(final View targetView, final int start, final int end) {
// 1
ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
// 2
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
private final static String ANIM_TAG = "##Value animator";
private IntEvaluator mIntEvaluator = new IntEvaluator();
@Override
public void onAnimationUpdate(ValueAnimator animator) {
int currentValue = (Integer) animator.getAnimatedValue();
Log.d(ANIM_TAG, "current value: " + currentValue);
// 3
float fraction = animator.getAnimatedFraction();
targetView.getLayoutParams().width = mIntEvaluator.evaluate(fraction, start, end);
targetView.requestLayout();
}
});
// 4
valueAnimator.setDuration(1000).start();
}
ValueAnimator
でアニメーションを作ります.ValueAnimator
は実質的に何もしません.だから、後のAnimatorUpdateListener
が太い仕事をする必要があります.ここで指定した1から100までは実質的な役割はありません.ボタンの幅を1から100に変えるわけではありません.後ろのコードはこの点をはっきりと表現しています.AnimatorUpdateListener
を追加します.最も重要なのは方法public void onAnimationUpdate(ValueAnimator animator)
でアニメーションを作ることです.このメソッドは、タイムスライスごとに呼び出されます.このメソッドを呼び出すたびに、このボタンの幅に新しい値を設定します.fraction
である.次に、このパーセントに基づいて、現在のタイムスライスに対応するボタン幅を計算します.現在の幅=初期幅+fraction*(終了幅-初期幅).これは、コードmIntEvaluator.evaluate(fraction, start, end)
の役割を説明する.完全なコードはここを見てください.ここまで全部説明します.レンガを撮ることを歓迎して、討論を歓迎します!