和使用Path()绘制图形一样使用动画

和使用Path()绘制图形一样使用动画

1.遇到的问题

当我们要将一个控件进行复杂的移动的时候,我们需要定义很多的移动路径。显得很繁琐,能否有一个更好的框架能实现了。当我们在绘制图形的时候会使用一个Path()类,它提供了和多方法,可以moveTo,lineTo,curvTo等方法进行保存使用到的点。于是,能否自定义一个类似的框架,也保存一系列的点,然后通过属性动画的方式把一起绘制出了。

2.实现方式

2.1 定义一个PathPoint来描述各个点的属性

现在以直线和三阶贝塞尔曲线为类定义属性

public class PathPoint {

    public static final int MOVE = 0;
    //直线
    public static final int LINE = 1;
    //三阶贝塞尔曲线
    public static final int CURV = 3;

    public float mX = 0;
    public float mY = 0;
    public int mOperation = MOVE;
    
    public float mControl0X = 0;
    public float mControl0Y = 0;
    
    public float mControl1X = 0;
    public float mControl1Y = 0;

    public PathPoint() {
        mX = 0;
        mY = 0;
        mOperation = MOVE;
        
        mControl0X = 0;
        mControl0Y = 0;
        
        mControl1X = 0;
        mControl1Y = 0;
    }
}

2.2 定义保存各路径的类 AnimatorPath

ArrayList path = new ArrayList();

    public void move(int i, int j) {
        PathPoint point = new PathPoint();
        point.mX = i;
        point.mY = j;
        point.mOperation = PathPoint.MOVE;
        path.add(point);

    }

    public void curvTo(int i, int j, int k, int l, int m, int n) {
        PathPoint point = new PathPoint();
        point.mX = i;
        point.mY = j;
        point.mControl0X = k;
        point.mControl0Y = l;
        point.mControl1X = m;
        point.mControl1Y = n;
        point.mOperation = PathPoint.CURV;
        path.add(point);
    }

    public ArrayList getPath() {
        return path;
    }

    public void setPath(ArrayList path) {
        this.path = path;
    }

    public void lineTo(int i, int j) {
        PathPoint point = new PathPoint();
        point.mX = i;
        point.mY = j;
        point.mOperation = PathPoint.LINE;
        path.add(point);
    }
}

2.3 怎么调用

public void ButtonOnClick() {
        AnimatorPath path = new AnimatorPath();
        path.move(0, 0);
        // path.lineTo(200,-100);
        path.curvTo(-800, 200, -600, 100, -900, 200);

        // path.curvTo(200,200,400,100,600,50);
        ObjectAnimator anim = ObjectAnimator.ofObject(this, "fabLoc",
                new PathEvaluator(), path.getPath().toArray());
        anim.setInterpolator(new AccelerateInterpolator());
        anim.setDuration(1500);
    }
    
    public void setFabLoc(PathPoint newLoc) {
        Log.e("TXB", "newLoc.mX = " + newLoc.mX);
        imagebut.setTranslationX(newLoc.mX);
        imagebut.setTranslationY(newLoc.mY);
    }

注意: 1.ObjectAnimator.ofObject使用的方法第二个参数可以随便写,但是必须实现一个public对应的方法。例子中必须实现一个setFabLoc方法,来更新得到点的平移。
2.PathEvaluator 是一个估值器,是用来计算最新点的数据。下节详细介绍。
3.最后一个参数是所有保存的路径的点,这些点提供个PathEvaluator进行计算的数据。

2.4 PathEvaluator估值器

public class PathEvaluator implements TypeEvaluator {

    @Override
    public PathPoint evaluate(float t, PathPoint startValue, PathPoint endValue) {
        PathPoint point = new PathPoint();
        
        //三阶贝塞尔曲线计算
        if (endValue.mOperation == PathPoint.CURV) {
            float oneMinusT = 1 - t;
            point.mX = oneMinusT * oneMinusT * oneMinusT * startValue.mX + 3
                    * oneMinusT * oneMinusT * t * endValue.mControl0X + 3
                    * oneMinusT * t * t * endValue.mControl1X + t * t * t
                    * endValue.mX;
            point.mY = oneMinusT * oneMinusT * oneMinusT * startValue.mY + 3
                    * oneMinusT * oneMinusT * t * endValue.mControl0Y + 3
                    * oneMinusT * t * t * endValue.mControl1Y + t * t * t
                    * endValue.mY;
        } else if (endValue.mOperation == PathPoint.LINE) {
            //直线运动
            point.mX =startValue.mX + t*(endValue.mX - startValue.mX);
            point.mY =startValue.mY + t*(endValue.mY - startValue.mY);
        } else {
            point.mX = startValue.mX;
            point.mY = startValue.mY;
        }
        
        point.mOperation = endValue.mOperation;
        return point;
    }

}

PS:计算公式


image

你可能感兴趣的:(和使用Path()绘制图形一样使用动画)