8

パスの描画をアニメーション化する、つまり、画面に徐々に表示されるようにしたいと思います。私はキャンバスを使用していますが、これまでのところ、ObjectAnimatorを使用してアニメーションを処理するのが最善の推測です。ただし、onDraw()メソッドでパスの対応するセグメントを実際に描画する方法を理解できません。これを可能にする方法はありますか?そのためにパス効果を含める必要がありますか?

編集: DashPathEffectを使用し、アニメーションで「オン」と「オフ」の間隔を設定して、そのステップで描画するパスの部分をカバーするように設定すると、ここでは機能するようですが、ステップごとに新しいDashPathEffectを割り当てる必要があります。アニメーション。より良い方法がある場合に備えて、質問は開いたままにしておきます。

4

3 に答える 3

13

私自身の質問に答えて、それを行うための満足のいく方法を見つけました。

秘訣は、を使用しObjectAnimatorて現在のストロークの長さを段階的に変更し、aを使用DashPathEffectして現在のストロークの長さを制御することです。ダッシュパラメータは、最初は次のDashPathEffectように設定されます。

float[] dashes = { 0.0f, Float.MAX_VALUE };

最初のフロートは表示されているストロークの長さであり、2番目のフロートは非表示部分の長さです。2番目の長さは非常に高くなるように選択されています。したがって、初期設定は完全に見えないストロークに対応します。

次に、オブジェクトアニメーターがストロークの長さの値を更新するたびにDashPathEffect、新しい表示パーツで新しいものが作成され、Painterオブジェクトに設定され、ビューが無効になります。

dashes[0] = newValue;
mPaint.setPathEffect(new DashPathEffect(dashes, 0));
invalidate();

最後に、onDraw()メソッドは、このペインタを使用してパスを描画します。パスは、必要な部分のみを構成します。

canvas.drawPath(path, mPaint);

私が見る唯一の欠点は、アニメーションのすべてのステップで新しいDashPathEffectを作成する必要があることです(再利用できないため)が、グローバルにこれは満足のいくものです-アニメーションは素晴らしくスムーズです。

于 2012-10-14T08:25:41.447 に答える
1
package com.nexoslav.dashlineanimatedcanvasdemo;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;

import androidx.annotation.Nullable;

public class CustomView extends View {
    float[] dashes = {30, 20};
    Paint mPaint;
    private Path mPath;

    private void init() {

        mPaint = new Paint();
        mPaint.setColor(Color.BLACK);
        mPaint.setStrokeWidth(10f);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setPathEffect(new DashPathEffect(dashes, 0));

        mPath = new Path();
        mPath.moveTo(200, 200);
        mPath.lineTo(300, 100);
        mPath.lineTo(400, 400);
        mPath.lineTo(1000, 200);
        mPath.lineTo(1000, 1000);
        mPath.lineTo(200, 400);

        ValueAnimator animation = ValueAnimator.ofInt(0, 100);
        animation.setInterpolator(new LinearInterpolator());
        animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                Log.d("bla", "bla: " + valueAnimator.getAnimatedValue());
                mPaint.setPathEffect(new DashPathEffect(dashes, (Integer) valueAnimator.getAnimatedValue()));
                invalidate();
            }
        });
        animation.setDuration(1000);
        animation.setRepeatMode(ValueAnimator.RESTART);
        animation.setRepeatCount(ValueAnimator.INFINITE);
        animation.start();
    }

    public CustomView(Context context) {
        super(context);
        init();
    }


    public CustomView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.drawPath(mPath, mPaint);
    }
}
于 2020-02-24T21:29:29.240 に答える
0

私の知る限り、唯一の方法は、空のパスから開始し、パスが完了するまで、定義された間隔でパスにポイントを追加するランナブルを用意することです。

于 2012-10-07T14:54:35.990 に答える