android之Animation自定义动画轨迹

以下面一个实例来说说这个Animation自定义动画怎么使用。

android之Animation自定义动画轨迹_第1张图片

图中,我们可以看出,小球是带有轨迹的向下滚动,而且,轨道与轨道之间的拼接是用二阶贝塞尔曲线实现的,小球模拟重力效果,加速度的向下滚。那么,这里有疑问的地方是,如果模拟这个场景去实现呢?

首先我们想到了用android的动画Animation。

我们对Animation进行了深究,发现有一个ObjectAnimator的类,其中创建的时候,就有个相关的参数TypeEvaluator和Object,只要实现这两个类,就能做成我们想要的轨迹效果。

不啰嗦,贴上代码

public class PathEvaluator implements TypeEvaluator {

    /**
     * @param t          :执行的百分比
     * @param startValue : 起点
     * @param endValue   : 终点
     * @return
     */
    @Override
    public PathPoint evaluate(float t, PathPoint startValue, PathPoint endValue) {
        float x, y;
        float oneMiunsT = 1 - t;
        //三阶贝塞尔曲线
        if (endValue.mOperation == PathPoint.THIRD_CURVE) {
            x = startValue.mX*oneMiunsT*oneMiunsT*oneMiunsT+3*endValue.mContorl0X*t*oneMiunsT*oneMiunsT+3*endValue.mContorl1X*t*t*oneMiunsT+endValue.mX*t*t*t;
            y = startValue.mY*oneMiunsT*oneMiunsT*oneMiunsT+3*endValue.mContorl0Y*t*oneMiunsT*oneMiunsT+3*endValue.mContorl1Y*t*t*oneMiunsT+endValue.mY*t*t*t;
        //二阶贝塞尔曲线
        }else if(endValue.mOperation == PathPoint.SECOND_CURVE){
            x = oneMiunsT*oneMiunsT*startValue.mX+2*t*oneMiunsT*endValue.mContorl0X+t*t*endValue.mX;
            y = oneMiunsT*oneMiunsT*startValue.mY+2*t*oneMiunsT*endValue.mContorl0Y+t*t*endValue.mY;
        //直线
        }else if (endValue.mOperation == PathPoint.LINE) {
            //x起始点+t*起始点和终点的距离
            x = startValue.mX + t * (endValue.mX - startValue.mX);
            y = startValue.mY + t * (endValue.mY - startValue.mY);
        } else {
            x = endValue.mX;
            y = endValue.mY;
        }
        return PathPoint.moveTo(x,y);
    }
}


public class AnimatorPath {
    //一系列的轨迹记录动作
    private List mPoints = new ArrayList<>();

    /**
     * 移动位置到:
     * @param x
     * @param y
     */
    public void moveTo(float x,float y){
        mPoints.add(PathPoint.moveTo(x,y));
    }

    /**
     * 直线移动
     * @param x
     * @param y
     */
    public void lineTo(float x,float y){
        mPoints.add(PathPoint.lineTo(x,y));
    }

    /**
     * 二阶贝塞尔曲线移动
     * @param c0X
     * @param c0Y
     * @param x
     * @param y
     */
    public void secondBesselCurveTo(float c0X, float c0Y,float x,float y){
        mPoints.add(PathPoint.secondBesselCurveTo(c0X,c0Y,x,y));
    }

    /**
     * 三阶贝塞尔曲线移动
     * @param c0X
     * @param c0Y
     * @param c1X
     * @param c1Y
     * @param x
     * @param y
     */
    public void thirdBesselCurveTo(float c0X, float c0Y, float c1X, float c1Y, float x, float y){
        mPoints.add(PathPoint.thirdBesselCurveTo(c0X,c0Y,c1X,c1Y,x,y));
    }
    /**
     *
     * @return  返回移动动作集合
     */
    public Collection getPoints(){
        return mPoints;
    }
}

    public AnimatorPath getRandomPath() {
        ArrayList array = new ArrayList<>();
        animatorPath = new AnimatorPath();
        Point point = new Point();
        point.set(startPoint.x, startPoint.y);

        animatorPath.moveTo(point.x, point.y);
        for (int i = 1; i <= maxTurn; i++) {
            if (i % 2 == 1) {
                boolean isLeft = isLeft();
                array.add(isLeft);
                point = isLeft ? makeLeftPath(point) : makeRightPath(point);
            } else if (i % 2 == 0) {
                boolean isLeft = isLeft();
                array.add(isLeft);

                if (i != maxTurn) {
                    point = isLeft ? makeLeftPath(point) : makeRightPath(point);
                    if (array.size() > 1 && array.get(array.size() - 2) == isLeft) {
                        point = isLeft ? makeRightPath(point) : makeLeftPath(point);
                        i += 1;
                    }
                } else {
                    point = isLeft ? makeLeftEndPath(point) : makeRightEndPath(point);
                }
            }
        }
        return animatorPath;
    }

    private void startAnimatorPath(View view, String propertyName, AnimatorPath path) {
        if (anim != null && anim.isStarted()) {
            isStart = false;
            anim.cancel();
        }

        isStart = true;
        anim = ObjectAnimator.ofObject(this, propertyName, new PathEvaluator(), path.getPoints().toArray());
        anim.setInterpolator(new AccelerateInterpolator(0.85f));
        anim.setDuration(8000);
        anim.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (vibrator != null && isStart) {
                    vibrator.vibrate(pattern, -1);    //重复两次上面的pattern 如果只想震动一次,index设为-1
                }
                if (mInterstitialAd.isLoaded()) {
                    mInterstitialAd.show();
                } else {
                    Log.e("xx", "none");
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        anim.start();
    }



你可能感兴趣的:(android进阶)