Android线路变形动画

时间:2015-02-15 23:58:04

标签: android android-animation android-canvas android-view

我基本上有两条线,由我画布上的两条路径绘制。每个人只有两个点,一个应该保持静止而另一个则移动。我只是通过创建一个Path然后调用moveTo(x1,y1)和lineTo(x2,y2)来实现这一点。

(x1,y1)在时间上永远不会改变,我想在(x2,y2)改变时实现动画。

以下是我现在的代码:

public class ProgressDownload extends View {

private static final String LOG_TAG = ProgressDownload.class.getSimpleName();

private static final int STROKE_WIDTH = 10;
private static final int PADDING = 50;
private static final String BACKGROUND_COLOR = "#EC5745";

private int mWidth, mHeight;
private int mProgress;
private Path mPathBlack, mPathWhite;
private Paint mPaintBlack, mPaintWhite;
private PathEffect mPathBlackEffect, mPathWhiteEffect;

public ProgressDownload(Context context, AttributeSet attrs) {
    super(context, attrs);

    setBackgroundColor(Color.parseColor(BACKGROUND_COLOR));
    setPadding(PADDING, 0, 50, PADDING);

    mPaintBlack = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaintBlack.setStyle(Paint.Style.STROKE);
    mPaintBlack.setStrokeWidth(STROKE_WIDTH);
    mPaintBlack.setColor(Color.BLACK);

    mPaintWhite = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaintWhite.setStyle(Paint.Style.STROKE);
    mPaintWhite.setStrokeWidth(STROKE_WIDTH);
    mPaintWhite.setColor(Color.WHITE);

    mPathBlackEffect = new CornerPathEffect(10);
    mPathWhiteEffect = new CornerPathEffect(10);
}

@Override
protected void onDraw(Canvas canvas) {
    if(mPathWhite != null && mPathBlack != null) {
        mPaintBlack.setPathEffect(mPathBlackEffect);
        mPaintWhite.setPathEffect(mPathWhiteEffect);

        canvas.drawPath(mPathBlack, mPaintBlack);
        canvas.drawPath(mPathWhite, mPaintWhite);
    }
}

@Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld) {
    super.onSizeChanged(xNew, yNew, xOld, yOld);
    mWidth = xNew - getPaddingRight();
    mHeight = yNew;
    Log.d(LOG_TAG, String.format("width and height measured are %d and %d", mWidth, mHeight));

    setPercentage(0);
}

private Path makePathBlack() {
    Path p =  new Path();

    p.moveTo(Math.max(getPaddingLeft(), mProgress*mWidth/100), mHeight/2 + calculatedeltaY());
    p.lineTo(mWidth, mHeight/2);

    return p;
}

private Path makePathWhite() {
    Path p = new Path();

    p.moveTo(getPaddingLeft(), mHeight / 2);
    p.lineTo(Math.max(getPaddingLeft(), mProgress*mWidth/100), mHeight/2 + calculatedeltaY());

    return p;
}

private int calculatedeltaY() {
    if(mProgress <= 50) {
        return  (mProgress * mWidth/6)/50;
    } else {
        return  ((100-mProgress) * mWidth/6)/50;
    }
}

public void setPercentage(int percentage) {
    if(percentage < 0 || percentage > 100)
        throw new IllegalArgumentException("setPercentage not between 0 and 100");
    mProgress = percentage;
    mPathBlack = makePathBlack();
    mPathWhite = makePathWhite();
    invalidate();
}
}

我在路径动画中看到了很多可能性,我想我需要一些东西来更新我当前的路径到新的路径。

setPercentage()这里根据传递的值更新两个路径。目前,新旧路径之间的过渡有点“野蛮”。有关于此的任何建议吗?

1 个答案:

答案 0 :(得分:1)

我突然开始研究对象动画师。解决方案是使用从当前百分比动画到新百分比的动画。结果正是我想要的。这是更新后的视图:

public class ProgressDownload extends View {

private static final String LOG_TAG = ProgressDownload.class.getSimpleName();

private static final int STROKE_WIDTH = 10;
private static final int PADDING = 50;
private static final long ANIMATION_DURATION = 1000;
private static final String BACKGROUND_COLOR = "#EC5745";

private int mWidth, mHeight;
private int mProgress = 0;
private Path mPathBlack, mPathWhite;
private Paint mPaintBlack, mPaintWhite;
private PathEffect mPathBlackEffect, mPathWhiteEffect;

public ProgressDownload(Context context, AttributeSet attrs) {
    super(context, attrs);

    setBackgroundColor(Color.parseColor(BACKGROUND_COLOR));
    setPadding(PADDING, 0, 50, PADDING);

    mPaintBlack = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaintBlack.setStyle(Paint.Style.STROKE);
    mPaintBlack.setStrokeWidth(STROKE_WIDTH);
    mPaintBlack.setColor(Color.BLACK);

    mPaintWhite = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaintWhite.setStyle(Paint.Style.STROKE);
    mPaintWhite.setStrokeWidth(STROKE_WIDTH);
    mPaintWhite.setColor(Color.WHITE);

    mPathBlackEffect = new CornerPathEffect(10);
    mPathWhiteEffect = new CornerPathEffect(10);
}

@Override
protected void onDraw(Canvas canvas) {
    if(mPathWhite != null && mPathBlack != null) {
        mPaintBlack.setPathEffect(mPathBlackEffect);
        mPaintWhite.setPathEffect(mPathWhiteEffect);

        canvas.drawPath(mPathBlack, mPaintBlack);
        canvas.drawPath(mPathWhite, mPaintWhite);
    }
}

@Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld) {
    super.onSizeChanged(xNew, yNew, xOld, yOld);
    mWidth = xNew - getPaddingRight();
    mHeight = yNew;
    Log.d(LOG_TAG, String.format("width and height measured are %d and %d", mWidth, mHeight));

    setPercentage(mProgress);
}

private Path makePathBlack() {

    if(mPathBlack ==null) {
        mPathBlack = new Path();
    }

    Path p =  new Path();
    p.moveTo(Math.max(getPaddingLeft(), mProgress*mWidth/100), mHeight/2 + calculatedeltaY());
    p.lineTo(mWidth, mHeight/2);

    mPathBlack.set(p);

    return p;
}

private void makePathWhite() {

    if(mPathWhite ==null) {
        mPathWhite = new Path();
    }

    Path p = new Path();
    p.moveTo(getPaddingLeft(), mHeight / 2);
    p.lineTo(Math.max(getPaddingLeft(), mProgress * mWidth / 100), mHeight / 2 + calculatedeltaY());

    mPathWhite.set(p);
}

private int calculatedeltaY() {
    if(mProgress <= 50) {
        return  (mProgress * mWidth/6)/50;
    } else {
        return  ((100-mProgress) * mWidth/6)/50;
    }
}

public void setPercentage(int newProgress) {
    if(newProgress < 0 || newProgress > 100)
        throw new IllegalArgumentException("setPercentage not between 0 and 100");

    ObjectAnimator anim = ObjectAnimator.ofInt(this, "progress", getProgress(), newProgress);
    anim.setDuration(ANIMATION_DURATION);
    anim.setInterpolator(new LinearInterpolator());
    anim.start();
}

public void setProgress(int progress) {
    mProgress = progress;
    makePathBlack();
    makePathWhite();
    invalidate();
}

public int getProgress() {
    return mProgress;
}
}