I have some code which creates a list of points called path.
Here is a sample list: [[1, 3], [2, 3], [2, 4]]
Here is the code I wrote to animate movement to these points sequentially:
ArrayList<Animator> movements = new ArrayList<>();
int prevY = start[1];
int prevX = start[0];
for (int[] square : path) {
ObjectAnimator motion = new ObjectAnimator();
float[] coord = screenFromGrid(square[0], square[1], gridSizeY);
long speed = (long) (6000.0 / this.displayMetrics.widthPixels);
speed = (long) (speed * getSquareSize(gridSizeY));
if (square[0] != prevX) {
motion = ObjectAnimator.ofFloat(this.sprite1, "x", coord[0]);
motion.setInterpolator(new LinearInterpolator());
motion.setDuration(speed);
movements.add(motion);
prevX = square[0];
} else if (square[1] != prevY) {
motion = ObjectAnimator.ofFloat(this.sprite1, "y", coord[1]);
motion.setInterpolator(new LinearInterpolator());
motion.setDuration(speed);
movements.add(motion);
prevY = square[1];
}
}
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playSequentially(movements);
animatorSet.start();
The problem is that animation completely stops in the middle without throwing any error.
I checked the debugger and it says all the animations have been stored properly.
Does anyone know why this is happening?
All I know from experience is, that AnimatorSet is buggy, and does not always work as expected, I have also had my issues with it, and luckily found another, better approach : ViewPropertyAnimator is a nice way to animate Views with short and concise code. You could write your own method which you can modify and reuse as wanted, something like :
private void customAnimation(View view, float toX, float toY, int duration, boolean loop) {
view.animate()
.translationX(toX)
.translationY(toY)
.setDuration(duration)
.setInterpolator(new LinearInterpolator())
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if(loop) {
customAnimation(..., false);
}
}
});
The listener waits for the first animation to finish, so you can call the next animation there. To play sequentially without looping forever I have added a boolean to the parameters which only executes the next animation if true.
That would also shorten the rest of your code to something like this :
int prevY = start[1];
int prevX = start[0];
for (int[] square : path) {
float[] coord = screenFromGrid(square[0], square[1], gridSizeY);
long speed = (long) (6000.0 / this.displayMetrics.widthPixels);
speed = (long) (speed * getSquareSize(gridSizeY));
if (square[0] != prevX) {
customAnimation(this.sprite1, coord[0], 0, speed, true);
prevX = square[0];
} else if (square[1] != prevY) {
customAnimation(this.sprite1, 0, coord[1], speed, true);
prevY = square[1];
}
}
Be sure to check the docs for all available methods, maybe .translationXBy(float byX) is more suited in your case than .translationX(float toX)