Add more reverse support to AnimatedVD

bug:16162242

Change-Id: Ie0b7618beeb65ebeb65db41600165837524bcee4
This commit is contained in:
ztenghui
2014-07-15 15:12:12 -07:00
committed by Tenghui Zhu
parent ce83a28c24
commit 7bc6a3f023
9 changed files with 152 additions and 11 deletions

View File

@@ -356,6 +356,22 @@ public abstract class Animator implements Cloneable {
public void setTarget(Object target) {
}
// Hide reverse() and canReverse() for now since reverse() only work for simple
// cases, like we don't support sequential, neither startDelay.
// TODO: make reverse() works for all the Animators.
/**
* @hide
*/
public boolean canReverse() {
return false;
}
/**
* @hide
*/
public void reverse() {
}
/**
* <p>An animation listener receives notifications from an animation.
* Notifications indicate animation related events, such as the end or the

View File

@@ -124,7 +124,7 @@ public final class AnimatorSet extends Animator {
// was set on this AnimatorSet, so it should not be passed down to the children.
private TimeInterpolator mInterpolator = null;
private boolean mReversible = true;
/**
* Sets up this AnimatorSet to play all of the supplied animations at the same time.
* This is equivalent to calling {@link #play(Animator)} with the first animator in the
@@ -177,6 +177,7 @@ public final class AnimatorSet extends Animator {
if (items.length == 1) {
play(items[0]);
} else {
mReversible = false;
for (int i = 0; i < items.length - 1; ++i) {
play(items[i]).before(items[i+1]);
}
@@ -196,6 +197,7 @@ public final class AnimatorSet extends Animator {
if (items.size() == 1) {
play(items.get(0));
} else {
mReversible = false;
for (int i = 0; i < items.size() - 1; ++i) {
play(items.get(i)).before(items.get(i+1));
}
@@ -407,6 +409,9 @@ public final class AnimatorSet extends Animator {
*/
@Override
public void setStartDelay(long startDelay) {
if (mStartDelay > 0) {
mReversible = false;
}
mStartDelay = startDelay;
}
@@ -512,7 +517,7 @@ public final class AnimatorSet extends Animator {
node.animation.setInterpolator(mInterpolator);
}
}
// First, sort the nodes (if necessary). This will ensure that sortedNodes
// First, sort the nodes (if necessary). This will ensure that sortedNodes
// contains the animation nodes in the correct order.
sortNodes();
@@ -626,6 +631,7 @@ public final class AnimatorSet extends Animator {
anim.mNodeMap = new HashMap<Animator, Node>();
anim.mNodes = new ArrayList<Node>();
anim.mSortedNodes = new ArrayList<Node>();
anim.mReversible = mReversible;
// Walk through the old nodes list, cloning each node and adding it to the new nodemap.
// One problem is that the old node dependencies point to nodes in the old AnimatorSet.
@@ -907,6 +913,35 @@ public final class AnimatorSet extends Animator {
}
}
/**
* @hide
*/
@Override
public boolean canReverse() {
if (!mReversible) {
return false;
}
// Loop to make sure all the Nodes can reverse.
for (Node node : mNodes) {
if (!node.animation.canReverse() || node.animation.getStartDelay() > 0) {
return false;
}
}
return true;
}
/**
* @hide
*/
@Override
public void reverse() {
if (canReverse()) {
for (Node node : mNodes) {
node.animation.reverse();
}
}
}
/**
* Dependency holds information about the node that some other node is
* dependent upon and the nature of that dependency.
@@ -1124,6 +1159,7 @@ public final class AnimatorSet extends Animator {
* {@link AnimatorSet#play(Animator)} method ends.
*/
public Builder before(Animator anim) {
mReversible = false;
Node node = mNodeMap.get(anim);
if (node == null) {
node = new Node(anim);
@@ -1144,6 +1180,7 @@ public final class AnimatorSet extends Animator {
* {@link AnimatorSet#play(Animator)} method to play.
*/
public Builder after(Animator anim) {
mReversible = false;
Node node = mNodeMap.get(anim);
if (node == null) {
node = new Node(anim);

View File

@@ -1038,6 +1038,7 @@ public class ValueAnimator extends Animator {
* play backwards. This behavior is only set for the current animation; future playing
* of the animation will use the default behavior of playing forward.
*/
@Override
public void reverse() {
mPlayingBackwards = !mPlayingBackwards;
if (mPlayingState == RUNNING) {
@@ -1052,6 +1053,14 @@ public class ValueAnimator extends Animator {
}
}
/**
* @hide
*/
@Override
public boolean canReverse() {
return true;
}
/**
* Called internally to end an animation by removing it from the animations list. Must be
* called on the UI thread.

View File

@@ -26,6 +26,7 @@ import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.util.LongSparseLongArray;
import android.util.SparseIntArray;
import android.util.StateSet;
@@ -62,6 +63,8 @@ import java.io.IOException;
* @attr ref android.R.styleable#DrawableStates_state_pressed
*/
public class AnimatedStateListDrawable extends StateListDrawable {
private static final String LOGTAG = AnimatedStateListDrawable.class.getSimpleName();
private static final String ELEMENT_TRANSITION = "transition";
private static final String ELEMENT_ITEM = "item";
@@ -302,13 +305,13 @@ public class AnimatedStateListDrawable extends StateListDrawable {
@Override
public boolean canReverse() {
return true;
return mAvd.canReverse();
}
@Override
public void start() {
if (mReversed) {
mAvd.reverse();
reverse();
} else {
mAvd.start();
}
@@ -316,7 +319,11 @@ public class AnimatedStateListDrawable extends StateListDrawable {
@Override
public void reverse() {
mAvd.reverse();
if (canReverse()) {
mAvd.reverse();
} else {
Log.w(LOGTAG, "Reverse() is called on a drawable can't reverse");
}
}
@Override

View File

@@ -337,15 +337,33 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable {
* Reverses ongoing animations or starts pending animations in reverse.
* <p>
* NOTE: Only works of all animations are ValueAnimators.
* @hide
*/
void reverse() {
public void reverse() {
final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
final int size = animators.size();
for (int i = 0; i < size; i++) {
final Animator animator = animators.get(i);
if (animator instanceof ValueAnimator) {
((ValueAnimator) animator).reverse();
if (animator.canReverse()) {
animator.reverse();
} else {
Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()");
}
}
}
/**
* @hide
*/
public boolean canReverse() {
final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
final int size = animators.size();
for (int i = 0; i < size; i++) {
final Animator animator = animators.get(i);
if (!animator.canReverse()) {
return false;
}
}
return true;
}
}

View File

@@ -19,7 +19,7 @@
android:drawable="@drawable/vector_drawable12" />
<item android:id="@+id/off"
android:drawable="@drawable/vector_drawable12" />
<transition android:fromId="@+id/off" android:toId="@+id/on">
<transition android:fromId="@+id/off" android:toId="@+id/on" android:reversible="true">
<animated-vector android:drawable="@drawable/vector_drawable12">
<target
android:name="pie1"

View File

@@ -0,0 +1,26 @@
<!--
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/on" android:state_checked="true"
android:drawable="@drawable/vector_drawable_grouping_1" />
<item android:id="@+id/off"
android:drawable="@drawable/vector_drawable_grouping_1" />
<transition android:fromId="@+id/off" android:toId="@+id/on"
android:drawable="@drawable/animation_vector_drawable_grouping_1"
android:reversible="true">
</transition>
</animated-selector>

View File

@@ -0,0 +1,26 @@
<!--
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/on" android:state_checked="true"
android:drawable="@drawable/vector_drawable_favorite" />
<item android:id="@+id/off"
android:drawable="@drawable/vector_drawable_favorite" />
<transition android:fromId="@+id/off" android:toId="@+id/on"
android:drawable="@drawable/animation_vector_drawable_favorite"
android:reversible="true">
</transition>
</animated-selector>

View File

@@ -27,7 +27,9 @@ public class AnimatedStateVectorDrawableTest extends Activity {
private static final String LOGCAT = "AnimatedStateVectorDrawableTest";
protected int[] icon = {
R.drawable.state_animation_vector_drawable
R.drawable.state_animation_vector_drawable01,
R.drawable.state_animation_vector_drawable02,
R.drawable.state_animation_vector_drawable03,
};
@Override
@@ -37,7 +39,7 @@ public class AnimatedStateVectorDrawableTest extends Activity {
ScrollView scrollView = new ScrollView(this);
GridLayout container = new GridLayout(this);
scrollView.addView(container);
container.setColumnCount(1);
container.setColumnCount(5);
for (int i = 0; i < icon.length; i++) {
CheckBox button = new CheckBox(this);