Merge "Refine the comparator for the animation event sorting"
This commit is contained in:
@@ -1333,7 +1333,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
|
||||
// Sort the list of events in ascending order of their time
|
||||
// Create the list including the delay animation.
|
||||
mEvents.clear();
|
||||
for (int i = 0; i < mNodes.size(); i++) {
|
||||
for (int i = 1; i < mNodes.size(); i++) {
|
||||
Node node = mNodes.get(i);
|
||||
mEvents.add(new AnimationEvent(node, AnimationEvent.ANIMATION_START));
|
||||
mEvents.add(new AnimationEvent(node, AnimationEvent.ANIMATION_DELAY_ENDED));
|
||||
@@ -1345,13 +1345,15 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
|
||||
long t1 = e1.getTime();
|
||||
long t2 = e2.getTime();
|
||||
if (t1 == t2) {
|
||||
if (e1.mNode == e2.mNode) {
|
||||
// For the same animation, start event has to happen before end.
|
||||
// For events that happen at the same time, we need them to be in the sequence
|
||||
// (end, start, start delay ended)
|
||||
if (e2.mEvent + e1.mEvent == AnimationEvent.ANIMATION_START
|
||||
+ AnimationEvent.ANIMATION_DELAY_ENDED) {
|
||||
// Ensure start delay happens after start
|
||||
return e1.mEvent - e2.mEvent;
|
||||
} else {
|
||||
return e2.mEvent - e1.mEvent;
|
||||
}
|
||||
// For different animation, end events need to happen before start, to ensure
|
||||
// sequential animations finish the previous one before starting the next one.
|
||||
return e2.mEvent - e1.mEvent;
|
||||
}
|
||||
if (t2 == DURATION_INFINITE) {
|
||||
return -1;
|
||||
@@ -1364,22 +1366,83 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
|
||||
}
|
||||
});
|
||||
|
||||
int eventSize = mEvents.size();
|
||||
// For the same animation, start event has to happen before end.
|
||||
for (int i = 0; i < eventSize;) {
|
||||
AnimationEvent event = mEvents.get(i);
|
||||
if (event.mEvent == AnimationEvent.ANIMATION_END) {
|
||||
boolean needToSwapStart;
|
||||
if (event.mNode.mStartTime == event.mNode.mEndTime) {
|
||||
needToSwapStart = true;
|
||||
} else if (event.mNode.mEndTime == event.mNode.mStartTime
|
||||
+ event.mNode.mAnimation.getStartDelay()) {
|
||||
// Swapping start delay
|
||||
needToSwapStart = false;
|
||||
} else {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
int startEventId = eventSize;
|
||||
int startDelayEndId = eventSize;
|
||||
for (int j = i + 1; j < eventSize; j++) {
|
||||
if (startEventId < eventSize && startDelayEndId < eventSize) {
|
||||
break;
|
||||
}
|
||||
if (mEvents.get(j).mNode == event.mNode) {
|
||||
if (mEvents.get(j).mEvent == AnimationEvent.ANIMATION_START) {
|
||||
// Found start event
|
||||
startEventId = j;
|
||||
} else if (mEvents.get(j).mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
|
||||
startDelayEndId = j;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (needToSwapStart && startEventId == mEvents.size()) {
|
||||
throw new UnsupportedOperationException("Something went wrong, no start is"
|
||||
+ "found after stop for an animation that has the same start and end"
|
||||
+ "time.");
|
||||
|
||||
}
|
||||
if (startDelayEndId == mEvents.size()) {
|
||||
throw new UnsupportedOperationException("Something went wrong, no start"
|
||||
+ "delay end is found after stop for an animation");
|
||||
|
||||
}
|
||||
|
||||
// We need to make sure start is inserted before start delay ended event,
|
||||
// because otherwise inserting start delay ended events first would change
|
||||
// the start event index.
|
||||
if (needToSwapStart) {
|
||||
AnimationEvent startEvent = mEvents.remove(startEventId);
|
||||
mEvents.add(i, startEvent);
|
||||
i++;
|
||||
}
|
||||
|
||||
AnimationEvent startDelayEndEvent = mEvents.remove(startDelayEndId);
|
||||
mEvents.add(i, startDelayEndEvent);
|
||||
i += 2;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mEvents.isEmpty() && mEvents.get(0).mEvent != AnimationEvent.ANIMATION_START) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Sorting went bad, the start event should always be at index 0");
|
||||
}
|
||||
|
||||
// Add AnimatorSet's start delay node to the beginning
|
||||
mEvents.add(0, new AnimationEvent(mRootNode, AnimationEvent.ANIMATION_START));
|
||||
mEvents.add(1, new AnimationEvent(mRootNode, AnimationEvent.ANIMATION_DELAY_ENDED));
|
||||
mEvents.add(2, new AnimationEvent(mRootNode, AnimationEvent.ANIMATION_END));
|
||||
|
||||
if (mEvents.get(mEvents.size() - 1).mEvent == AnimationEvent.ANIMATION_START
|
||||
|| mEvents.get(mEvents.size() - 1).mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Something went wrong, the last event is not an end event");
|
||||
}
|
||||
if (mEvents.get(1).mEvent != AnimationEvent.ANIMATION_DELAY_ENDED
|
||||
|| mEvents.get(1).mNode != mRootNode) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Sorting went bad, the root node's start delay end event should always be at"
|
||||
+ " index 1");
|
||||
}
|
||||
if (mEvents.get(2).mEvent != AnimationEvent.ANIMATION_END
|
||||
|| mEvents.get(2).mNode != mRootNode) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Sorting went bad, the start delay end event should always be at index 2");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user