和使用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<PathPoint> path = new ArrayList<PathPoint>();
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<PathPoint> getPath() {
return path;
}
public void setPath(ArrayList<PathPoint> 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<PathPoint> {
@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:计算公式