Android アニメーション コレクション属性アニメーション - もう一度見てください


このセクションの紹介:

前のセクションでは、Android 属性アニメーションについての予備調査を行いました。属性アニメーションについては、もう誰もが馴染みがないと思います。 ある程度の知識が得られたので、このセクションでは Android プロパティ アニメーションのより高度な使用方法を引き続き検討していきます。 Guo Shen による記事はまだ 3 つ投稿されています~

Android 属性アニメーションの完全分析 (パート 1)、初めての属性アニメーションの基本的な使い方

Android 属性アニメーションの完全分析 (パート 2)、高度な使い方ValueAnimator と ObjectAnimator

Android プロパティ アニメーションの完全な分析 (パート 2)、Interpolator と ViewPropertyAnimator の使用法

内容はまだ上記 3 つの記事に基づいています。よし、このセクションを始めましょう~


1.Evaluatorカスタマイズ

1) エバリュエーターの紹介

前のセクション8.4.3 Android アニメーション コレクションの属性アニメーション - ファースト ルック では、アニメーションを使用する最初のステップは次のとおりです:

ValueAnimator の ofInt()、 を呼び出すofFloat() または、ofObject() 静的メソッドを使用して、ValueAnimator インスタンスを作成します。

この例では、ofInt と ofFloat の両方を使用しており、それぞれ浮動小数点データと整数データをアニメーション化するために使用されます。

それで、ofObject()?初期オブジェクトと終了オブジェクト?移行方法は?それともこれをどうやって使うのですか?

それでは、質問として、まず 1 つのことを理解しましょう。実際、属性アニメーションの概念について話したときに、このことについて話しました。

1.png

は、アニメーション システムにどのように遷移するかを指示するために使用されます。初期値から終了値!よし、出発点は正しい! IntEvaluator のソース コードに何が書かれているか見てみましょう。

2.png

さて、TypeEvaluator インターフェースが実装され、次に evaluate() メソッドが順番に書き換えられます。

  • fraction: アニメーションの完成度。それに基づいてアニメーションを計算します 値はどうすればよいですか?
  • startValue: アニメーションの開始値
  • endValue: アニメーションの終了値

アニメーションの値 = 初期値 + 完了 * (終了値 - 初期値)

FloatEvaluator にも同じことが当てはまり、初期オブジェクトから終了オブジェクトへの遷移方法をシステムに指示する必要があります。 TypeEvaluator インターフェースを自分で実装します。つまり、Evaluator をカスタマイズします。これ以上は説明する必要はありません。

2) 使用例

レンダリングの実行:

3.gif

コード実装:

オブジェクト Point.java を定義します。このオブジェクトには、x と y の 2 つの属性と get メソッドと set メソッドしかありません~

/**
 * Created by Jay on 2015/11/18 0018.
 */
public class Point {

    private float x;
    private float y;

    public Point() {
    }

    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }

    public float getX() {
        return x;
    }

    public float getY() {
        return y;
    }

    public void setX(float x) {
        this.x = x;
    }

    public void setY(float y) {
        this.y = y;
    }
}

次に、Evaluator クラスをカスタマイズします: PointEvaluator.java 、インターフェイスを実装し、evaluate メソッドを書き換えます~

/**
 * Created by Jay on 2015/11/18 0018.
 */
public class PointEvaluator implements TypeEvaluator{
    @Override
    public Point evaluate(float fraction, Point startValue, Point endValue) {
        float x = startValue.getX() + fraction * (endValue.getX() - startValue.getX());
        float y = startValue.getY() + fraction * (endValue.getY() - startValue.getY());
        Point point = new Point(x, y);
        return point;
    }
}

、次に View クラスをカスタマイズします: AnimView.java、非常に簡単です~

/**
 * Created by Jay on 2015/11/18 0018.
 */
public class AnimView extends View {

    public static final float RADIUS = 80.0f;
    private Point currentPoint;
    private Paint mPaint;

    public AnimView(Context context) {
        this(context, null);
    }

    public AnimView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public AnimView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.BLUE);
    }

    private void drawCircle(Canvas canvas){
        float x = currentPoint.getX();
        float y = currentPoint.getY();
        canvas.drawCircle(x, y, RADIUS, mPaint);
    }

    private void startAnimation() {
        Point startPoint = new Point(RADIUS, RADIUS);
        Point endPoint = new Point(getWidth() - RADIUS, getHeight() - RADIUS);
        ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                currentPoint = (Point) animation.getAnimatedValue();
                invalidate();
            }
        });
        anim.setDuration(3000l);
        anim.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (currentPoint == null) {
            currentPoint = new Point(RADIUS, RADIUS);
            drawCircle(canvas);
            startAnimation();
        } else {
            drawCircle(canvas);
        }
    }
}

最後に、この View を MainActivity.java~

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new AnimView(this));
    }
}

3 でインスタンス化します。 ) 例 強化版

上記の例に基づいて、円が移動したときの色の変化を追加します~ ここでは、別の ObjectAnimator を使用して色変更アニメーションを複数追加します。 int color を使用して色を制御し、getColor() メソッドと setColor() メソッドを記述します。まず、Evaluator をカスタマイズしましょう~

実装コード:

4.gifColorEvaluator。 :

/**
 * Created by Jay on 2015/11/18 0018.
 */
public class ColorEvaluator implements TypeEvaluator{
    @Override
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int alpha = (int) (Color.alpha(startValue) + fraction *
                (Color.alpha(endValue) - Color.alpha(startValue)));
        int red = (int) (Color.red(startValue) + fraction *
                (Color.red(endValue) - Color.red(startValue)));
        int green = (int) (Color.green(startValue) + fraction *
                (Color.green(endValue) - Color.green(startValue)));
        int blue = (int) (Color.blue(startValue) + fraction *
                (Color.blue(endValue) - Color.blue(startValue)));
        return Color.argb(alpha, red, green, blue);
    }
}

次に、View をカスタマイズして色を追加し、ObjectAnimator を作成し、メソッドを取得および設定します。 読者が質問がある場合に備えて、ここでいくつかのことを追加します。 別の View を作成するだけです~

AnimView2.java

:

/**
 * Created by Jay on 2015/11/18 0018.
 */
public class AnimView2 extends View {

    public static final float RADIUS = 80.0f;
    private Point currentPoint;
    private Paint mPaint;
    private int mColor;

    public AnimView2(Context context) {
        this(context, null);
    }

    public AnimView2(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public AnimView2(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.BLUE);
    }



    private void drawCircle(Canvas canvas){
        float x = currentPoint.getX();
        float y = currentPoint.getY();
        canvas.drawCircle(x, y, RADIUS, mPaint);
    }

    private void startAnimation() {
        Point startPoint = new Point(RADIUS, RADIUS);
        Point endPoint = new Point(getWidth() - RADIUS, getHeight() - RADIUS);
        ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                currentPoint = (Point) animation.getAnimatedValue();
                invalidate();
            }
        });

        ObjectAnimator objectAnimator = ObjectAnimator.ofObject(this, "color", new ColorEvaluator(),
                Color.BLUE, Color.RED);
        //动画集合将前面两个动画加到一起,with同时播放
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.play(anim).with(objectAnimator);
        animatorSet.setStartDelay(1000l);
        animatorSet.setDuration(3000l);
        animatorSet.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (currentPoint == null) {
            currentPoint = new Point(RADIUS, RADIUS);
            drawCircle(canvas);
            startAnimation();
        } else {
            drawCircle(canvas);
        }
    }

    //color的get和set方法~
    public int getColor() {
        return mColor;
    }

    public void setColor(int color) {
        mColor = color;
        mPaint.setColor(color);
        invalidate();
    }
}
次に、MainActivity、setContentView、AnimView を AnimView2~

2.Interpolator (tweener) に変更します

さて、私たちはトゥイーンについて話しています。 the anime~まだ覚えてるかな?

上記のトゥイーナー アニメーションと属性アニメーションの両方が利用可能で、トゥイーン アニメーションには新しい

TimeInterpolator

インターフェースもあります このインターフェイスは以前の Interpolator と互換性を保つために使用されており、これにより過去のすべての Interpolator 実装クラスを直接使用できるようになります。 属性アニメーションで使用してください!アニメーション オブジェクトの setInterpolator() メソッドを呼び出して、さまざまなインターポレーターを設定できます。 最初に何かをクリックして、ボールを画面の中央の上から下に落とす必要があります~ 次に、セットしたアニメーションに対して次のステートメントを呼び出します:
animatorSet.setInterpolator(new AccelerateInterpolator(2f));

括弧内の値は加速を制御するために使用されます~

ランニングエフェクト

:

Itそれはちょっと常識的ではありません。代わりに

BounceInterpolator~

5.gif

を試してみましょう。もちろん、N 個以上のシステムが提供する優れた Interpolator があります。一度試してみてください。 もう心配しないでください~

見てみましょう:

1) Interpolator の内部実装メカニズム

まず、TimeInterpolator インターフェイスのソース コードにアクセスし、getInterpolation() メソッドが 1 つだけあることを確認します。

7.png

簡単な説明: getInterpolation() メソッドは入力パラメータを受け取ります。このパラメータの値は、アニメーションの実行中に変化し続けます。 ただし、その変化は非常に規則的で、設定されたアニメーション時間に応じて一定の速度で増加し、変化範囲は 0 ~ 1 です。 つまり、アニメーションが始まるときの input の値は 0、アニメーションが終了するときの input の値は 1、その中間の値は です。 アニメーションの実行に応じて 0 と 1 の間で変化します。

ここでの

inputの値は、TypeEvaluatorインターフェースのfractionの値を決定します。 入力値はシステムによって計算され、getInterpolation() メソッドに渡されます。その後、getInterpolation() メソッドにアルゴリズムを実装し、入力値に基づいて戻り値を計算できます。この戻り値は小数です。

LinearInterpolator

のコードを見てみましょう:

8.pngここには入力値を直接返す処理はありません。つまり、fractionの値はinputの値と等しく、これは一様です。モーション。 Interpolator の実装方法実際には、これもまた数学的な事柄を伴う異なるアルゴリズムにすぎません。 数学の重要性を理解したので、

BounceInterpolator

のソース コードを次に示します。

9.png ここでアルゴリズムについては聞かないでください。私も分かりません。もっと理解しやすいものを探しましょう。

AcceleratedEceleratedEceleratedEnterPolator

このinterpolatorは最初に加速してから減速します。 解決策: [0,1] までの入力の値の範囲から、cos の値の範囲は [π, 2π] であり、対応する値は -1 と 1 であると結論付けることができます。 この値を 2 で割って 0.5 を加えても、getInterpolation() メソッドによって返される最終結果の値は依然として [0,1] の範囲内にあります。 対応する曲線は次のとおりです:

つまり、最初に加速してから減速するプロセスです。 まあ、私はクズなのでもう遊べません...、上記はすべて郭おじさんの記事からのコピペです...私は静かにしたい...

2) カスタム Interpolator

さて、それについては後で考えましょう。まずカスタム Interpolator の例を書きましょう。 非常に簡単で、TimeInterpolatorインターフェースを実装し、getInterpolationメソッドを書き換えます

サンプルコードは以下の通りです

private class DecelerateAccelerateInterpolator implements TimeInterpolator {
    @Override
    public float getInterpolation(float input) {
        if (input < 0.5) {
            return (float) (Math.sin(input * Math.PI) / 2);
        } else {
            return 1 - (float) (Math.sin(input * Math.PI) / 2);
        }
    }
}

setInterpolator(new DecelerateAccelerateInterpolator())を呼び出して設定します~ スペースの都合上、写真は掲載しません~


3. ViewPropertyAnimator

3.1以降にシステムに追加された新機能により、Viewアニメーション操作がさらに便利になりました! 以前であれば、TextView を通常の状態から透明な状態に変更するには、次のように記述します:

ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 0f);  
animator.start();

ViewPropertyAnimator を使用して同じ効果を実現する方が理解しやすいです:

textview.animate().alpha(0f);

は、連続使用 もサポートしています。複数のアニメーションを組み合わせたり、期間を設定したり、インターポレーターを設定したり、など~

textview.animate().x(500).y(500).setDuration(5000)  
        .setInterpolator(new BounceInterpolator());

使用方法は非常に簡単です。使用する際はドキュメントを確認するだけです~。注意すべき詳細が以下にいくつかあります。

  • ViewPropertyAnimator の関数全体は、View クラスの新しい animate() メソッドに基づいています。 このメソッドは ViewPropertyAnimator のインスタンスを作成して返し、後続のすべてのメソッドが呼び出されます。 すべてのプロパティの設定は、このインスタンスを通じて行われます。
  • ViewPropertyAnimator を使用してアニメーションを定義すると、アニメーションが自動的に開始します。 そして、この仕組みは、新しいメソッドを追加し続ける限り、組み合わせアニメーションにも有効です。 この場合、ViewPropertyAnimator に設定されたすべてのメソッドが実行されても、すぐにはアニメーションが実行されません。 アニメーションが自動的に開始されます。もちろん、このデフォルトのメカニズムを使用したくない場合は、start() メソッドを明示的に呼び出してアニメーションを開始することもできます。
  • ViewPropertyAnimator のすべてのインターフェイスは連結構文を使用して設計されており、各メソッドの戻り値は次のようになります。 これはそれ自体のインスタンスなので、1 つのメソッドを呼び出した後、そのメソッドの別のメソッドを連続して直接呼び出すことができます。 関数はすべて直列に接続されており、わずか 1 行のコードであらゆる複雑なアニメーション関数を完成させることができます。

4. このセクションのサンプルコードをダウンロードします

AnimatorDemo3.zip

Githubでアニメーションコレクションプロジェクトを見つけました。ここにアドレスがあります:

BaseAnimationアニメーションコレクション

。アニメーションがどのように実装されているかは、ソースコードで自分で見ることができます~


このセクションの概要

さて、このセクションでは、Evaluator、Interpolator、 ViewPropertyAnimator、皆さんの知識が広がりましたか~ このセクションは Android の基本的な入門図でもあります この章の最後のセクションです。この章の内容を理解したら、カスタム コントロールについて学習してください。 あるいは、他の人が書いたカスタム コントロールを見れば、どこから始めればよいのか、たくさんの新しい顔に出会うことができるのか、もう混乱する必要はありません。

さて、Guo Shen さんの記事に感謝します。属性アニメーション部分のほとんどの内容は Guo Shen から直接転送されました。12.jpg ふふ、このセクションは以上です、ありがとうございます〜

PS: シミュレーターを変更した理由。次の図では N5 が披露されています...