summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2013-06-21 15:00:05 -0700
committerChet Haase <chet@google.com>2013-06-21 16:07:14 -0700
commit2ea7f8b9c5f903050d42c1af57406bf528979f45 (patch)
tree80f0c3fcb68c1842f28906a306e3b41468b2fef0
parent862a301bf9fd3d315948872873602ba7bcb043d4 (diff)
downloadframeworks_base-2ea7f8b9c5f903050d42c1af57406bf528979f45.zip
frameworks_base-2ea7f8b9c5f903050d42c1af57406bf528979f45.tar.gz
frameworks_base-2ea7f8b9c5f903050d42c1af57406bf528979f45.tar.bz2
Refactoring/simplifying Transition code/API
Transitions used to be three phase: - captureValues(): get all relevant property values in the affected view targets - setup(): set appropriate start values for affected views prior to any transitions being played - play(): create/play Animators for affected views Now the second and third phases have been collapsed (and named "play()"). This single step sets initial values for target views and creates any Animators that should be played during the transition. The transition mechanism stores these Animators and then starts them at the appropriate time in the overall transition. Issue #9507585 Transitions: Simplify Transition.play() design Change-Id: I3fc67599b38fe49eee885dc5d32444db90b7703b
-rw-r--r--api/current.txt13
-rw-r--r--core/java/android/view/transition/Crossfade.java126
-rw-r--r--core/java/android/view/transition/Fade.java124
-rw-r--r--core/java/android/view/transition/Move.java115
-rw-r--r--core/java/android/view/transition/Recolor.java46
-rw-r--r--core/java/android/view/transition/Rotate.java17
-rw-r--r--core/java/android/view/transition/Slide.java20
-rw-r--r--core/java/android/view/transition/TextChange.java23
-rw-r--r--core/java/android/view/transition/Transition.java117
-rw-r--r--core/java/android/view/transition/TransitionGroup.java70
-rw-r--r--core/java/android/view/transition/TransitionValues.java6
-rw-r--r--core/java/android/view/transition/Visibility.java62
-rw-r--r--tests/TransitionTests/AndroidManifest.xml7
-rw-r--r--tests/TransitionTests/res/layout/hierarchical_move.xml46
-rw-r--r--tests/TransitionTests/res/values/strings.xml6
-rw-r--r--tests/TransitionTests/src/com/android/transitiontests/HierarchicalMove.java104
16 files changed, 365 insertions, 537 deletions
diff --git a/api/current.txt b/api/current.txt
index 481521e..7281d01 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18389,7 +18389,6 @@ package android.print.pdf {
public final class PdfDocument {
method public void close();
- method protected final void finalize() throws java.lang.Throwable;
method public void finishPage(android.print.pdf.PdfDocument.Page);
method public java.util.List<android.print.pdf.PdfDocument.PageInfo> getPages();
method public static android.print.pdf.PdfDocument open();
@@ -28524,7 +28523,6 @@ package android.view.transition {
method protected void captureValues(android.view.transition.TransitionValues, boolean);
method public int getFadeBehavior();
method public int getResizeBehavior();
- method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
method public void setFadeBehavior(int);
method public void setResizeBehavior(int);
field public static final int FADE_BEHAVIOR_CROSSFADE = 0; // 0x0
@@ -28543,7 +28541,6 @@ package android.view.transition {
public class Move extends android.view.transition.Transition {
ctor public Move();
method protected void captureValues(android.view.transition.TransitionValues, boolean);
- method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
method public void setReparent(boolean);
method public void setResizeClip(boolean);
}
@@ -28551,13 +28548,11 @@ package android.view.transition {
public class Recolor extends android.view.transition.Transition {
ctor public Recolor();
method protected void captureValues(android.view.transition.TransitionValues, boolean);
- method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
}
public class Rotate extends android.view.transition.Transition {
ctor public Rotate();
method protected void captureValues(android.view.transition.TransitionValues, boolean);
- method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
}
public final class Scene {
@@ -28578,7 +28573,6 @@ package android.view.transition {
public class TextChange extends android.view.transition.Transition {
ctor public TextChange();
method protected void captureValues(android.view.transition.TransitionValues, boolean);
- method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
}
public abstract class Transition implements java.lang.Cloneable {
@@ -28597,14 +28591,13 @@ package android.view.transition {
method protected void onTransitionCancel();
method protected void onTransitionEnd();
method protected void onTransitionStart();
- method protected abstract android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
+ method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
method public void removeListener(android.view.transition.Transition.TransitionListener);
method public android.view.transition.Transition setDuration(long);
method public void setInterpolator(android.animation.TimeInterpolator);
method public void setStartDelay(long);
method public android.view.transition.Transition setTargetIds(int...);
method public android.view.transition.Transition setTargets(android.view.View...);
- method protected boolean setup(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
}
public static abstract interface Transition.TransitionListener {
@@ -28618,7 +28611,6 @@ package android.view.transition {
ctor public TransitionGroup(int);
method public void addTransitions(android.view.transition.Transition...);
method protected void captureValues(android.view.transition.TransitionValues, boolean);
- method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
method public void removeTransition(android.view.transition.Transition);
method public void setOrdering(int);
field public static final int SEQUENTIALLY = 1; // 0x1
@@ -28657,9 +28649,6 @@ package android.view.transition {
method protected android.animation.Animator appear(android.view.ViewGroup, android.view.transition.TransitionValues, int, android.view.transition.TransitionValues, int);
method protected void captureValues(android.view.transition.TransitionValues, boolean);
method protected android.animation.Animator disappear(android.view.ViewGroup, android.view.transition.TransitionValues, int, android.view.transition.TransitionValues, int);
- method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
- method protected boolean setupAppear(android.view.ViewGroup, android.view.transition.TransitionValues, int, android.view.transition.TransitionValues, int);
- method protected boolean setupDisappear(android.view.ViewGroup, android.view.transition.TransitionValues, int, android.view.transition.TransitionValues, int);
}
}
diff --git a/core/java/android/view/transition/Crossfade.java b/core/java/android/view/transition/Crossfade.java
index 1e9b6fa..7cfba70 100644
--- a/core/java/android/view/transition/Crossfade.java
+++ b/core/java/android/view/transition/Crossfade.java
@@ -140,18 +140,20 @@ public class Crossfade extends Transition {
}
@Override
- protected boolean setup(ViewGroup sceneRoot, TransitionValues startValues,
+ protected Animator play(ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
if (startValues == null || endValues == null) {
- return false;
+ return null;
}
final View view = endValues.view;
Map<String, Object> startVals = startValues.values;
Map<String, Object> endVals = endValues.values;
+ Rect startBounds = (Rect) startVals.get(PROPNAME_BOUNDS);
+ Rect endBounds = (Rect) endVals.get(PROPNAME_BOUNDS);
Bitmap startBitmap = (Bitmap) startVals.get(PROPNAME_BITMAP);
Bitmap endBitmap = (Bitmap) endVals.get(PROPNAME_BITMAP);
- Drawable startDrawable = (Drawable) startVals.get(PROPNAME_DRAWABLE);
- Drawable endDrawable = (Drawable) endVals.get(PROPNAME_DRAWABLE);
+ final BitmapDrawable startDrawable = (BitmapDrawable) startVals.get(PROPNAME_DRAWABLE);
+ final BitmapDrawable endDrawable = (BitmapDrawable) endVals.get(PROPNAME_DRAWABLE);
if (Transition.DBG) {
Log.d(LOG_TAG, "StartBitmap.sameAs(endBitmap) = " + startBitmap.sameAs(endBitmap) +
" for start, end: " + startBitmap + ", " + endBitmap);
@@ -163,80 +165,62 @@ public class Crossfade extends Transition {
overlay.add(endDrawable);
}
overlay.add(startDrawable);
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- protected Animator play(ViewGroup sceneRoot, TransitionValues startValues,
- TransitionValues endValues) {
- if (startValues == null || endValues == null) {
- return null;
- }
- Map<String, Object> startVals = startValues.values;
- Map<String, Object> endVals = endValues.values;
-
- final View view = endValues.view;
- Rect startBounds = (Rect) startVals.get(PROPNAME_BOUNDS);
- Rect endBounds = (Rect) endVals.get(PROPNAME_BOUNDS);
- final BitmapDrawable startDrawable = (BitmapDrawable) startVals.get(PROPNAME_DRAWABLE);
- final BitmapDrawable endDrawable = (BitmapDrawable) endVals.get(PROPNAME_DRAWABLE);
-
- // The transition works by placing the end drawable under the start drawable and
- // gradually fading out the start drawable. So it's not really a cross-fade, but rather
- // a reveal of the end scene over time. Also, animate the bounds of both drawables
- // to mimic the change in the size of the view itself between scenes.
- ObjectAnimator anim = ObjectAnimator.ofInt(startDrawable, "alpha", 0);
- anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- // TODO: some way to auto-invalidate views based on drawable changes? callbacks?
- view.invalidate(startDrawable.getBounds());
- }
- });
- ObjectAnimator anim1 = null;
- if (mFadeBehavior == FADE_BEHAVIOR_CROSSFADE) {
- anim1 = ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1);
- }
- if (Transition.DBG) {
- Log.d(LOG_TAG, "Crossfade: created anim " + anim + " for start, end values " +
- startValues + ", " + endValues);
- }
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- ViewOverlay overlay = (mFadeBehavior == FADE_BEHAVIOR_REVEAL) ?
- view.getOverlay() : ((ViewGroup) view.getParent()).getOverlay();
- overlay.remove(startDrawable);
- if (mFadeBehavior == FADE_BEHAVIOR_REVEAL) {
- overlay.remove(endDrawable);
+ // The transition works by placing the end drawable under the start drawable and
+ // gradually fading out the start drawable. So it's not really a cross-fade, but rather
+ // a reveal of the end scene over time. Also, animate the bounds of both drawables
+ // to mimic the change in the size of the view itself between scenes.
+ ObjectAnimator anim = ObjectAnimator.ofInt(startDrawable, "alpha", 0);
+ anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ // TODO: some way to auto-invalidate views based on drawable changes? callbacks?
+ view.invalidate(startDrawable.getBounds());
}
+ });
+ ObjectAnimator anim1 = null;
+ if (mFadeBehavior == FADE_BEHAVIOR_CROSSFADE) {
+ anim1 = ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1);
}
- });
- AnimatorSet set = new AnimatorSet();
- set.playTogether(anim);
- if (anim1 != null) {
- set.playTogether(anim1);
- }
- if (mResizeBehavior == RESIZE_BEHAVIOR_SCALE && !startBounds.equals(endBounds)) {
if (Transition.DBG) {
- Log.d(LOG_TAG, "animating from startBounds to endBounds: " +
- startBounds + ", " + endBounds);
+ Log.d(LOG_TAG, "Crossfade: created anim " + anim + " for start, end values " +
+ startValues + ", " + endValues);
+ }
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ ViewOverlay overlay = (mFadeBehavior == FADE_BEHAVIOR_REVEAL) ?
+ view.getOverlay() : ((ViewGroup) view.getParent()).getOverlay();
+ overlay.remove(startDrawable);
+ if (mFadeBehavior == FADE_BEHAVIOR_REVEAL) {
+ overlay.remove(endDrawable);
+ }
+ }
+ });
+ AnimatorSet set = new AnimatorSet();
+ set.playTogether(anim);
+ if (anim1 != null) {
+ set.playTogether(anim1);
}
- Animator anim2 = ObjectAnimator.ofObject(startDrawable, "bounds",
- sRectEvaluator, startBounds, endBounds);
- set.playTogether(anim2);
- if (mResizeBehavior == RESIZE_BEHAVIOR_SCALE) {
- // TODO: How to handle resizing with a CROSSFADE (vs. REVEAL) effect
- // when we are animating the view directly?
- Animator anim3 = ObjectAnimator.ofObject(endDrawable, "bounds",
+ if (mResizeBehavior == RESIZE_BEHAVIOR_SCALE && !startBounds.equals(endBounds)) {
+ if (Transition.DBG) {
+ Log.d(LOG_TAG, "animating from startBounds to endBounds: " +
+ startBounds + ", " + endBounds);
+ }
+ Animator anim2 = ObjectAnimator.ofObject(startDrawable, "bounds",
sRectEvaluator, startBounds, endBounds);
- set.playTogether(anim3);
+ set.playTogether(anim2);
+ if (mResizeBehavior == RESIZE_BEHAVIOR_SCALE) {
+ // TODO: How to handle resizing with a CROSSFADE (vs. REVEAL) effect
+ // when we are animating the view directly?
+ Animator anim3 = ObjectAnimator.ofObject(endDrawable, "bounds",
+ sRectEvaluator, startBounds, endBounds);
+ set.playTogether(anim3);
+ }
}
+ return set;
+ } else {
+ return null;
}
- return set;
}
@Override
diff --git a/core/java/android/view/transition/Fade.java b/core/java/android/view/transition/Fade.java
index f3a4a39..3c5b6fa 100644
--- a/core/java/android/view/transition/Fade.java
+++ b/core/java/android/view/transition/Fade.java
@@ -93,18 +93,6 @@ public class Fade extends Visibility {
}
@Override
- protected boolean setupAppear(ViewGroup sceneRoot,
- TransitionValues startValues, int startVisibility,
- TransitionValues endValues, int endVisibility) {
- View endView = (endValues != null) ? endValues.view : null;
- if ((mFadingMode & IN) != IN) {
- return false;
- }
- endView.setAlpha(0);
- return true;
- }
-
- @Override
protected Animator appear(ViewGroup sceneRoot,
TransitionValues startValues, int startVisibility,
TransitionValues endValues, int endVisibility) {
@@ -112,17 +100,16 @@ public class Fade extends Visibility {
if ((mFadingMode & IN) != IN) {
return null;
}
- // TODO: hack - retain original value from before setupAppear
+ endView.setAlpha(0);
return runAnimation(endView, 0, 1, null);
- // TODO: end listener to make sure we end at 1 no matter what
}
@Override
- protected boolean setupDisappear(ViewGroup sceneRoot,
+ protected Animator disappear(ViewGroup sceneRoot,
TransitionValues startValues, int startVisibility,
TransitionValues endValues, int endVisibility) {
if ((mFadingMode & OUT) != OUT) {
- return false;
+ return null;
}
View view;
View startView = (startValues != null) ? startValues.view : null;
@@ -153,6 +140,7 @@ public class Fade extends Visibility {
}
}
}
+ final int finalVisibility = endVisibility;
// TODO: add automatic facility to Visibility superclass for keeping views around
if (overlayView != null) {
// TODO: Need to do this for general case of adding to overlay
@@ -163,75 +151,55 @@ public class Fade extends Visibility {
overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
sceneRoot.getOverlay().add(overlayView);
- return true;
+ // TODO: add automatic facility to Visibility superclass for keeping views around
+ final float startAlpha = view.getAlpha();
+ float endAlpha = 0;
+ final View finalView = view;
+ final View finalOverlayView = overlayView;
+ final View finalViewToKeep = viewToKeep;
+ final ViewGroup finalSceneRoot = sceneRoot;
+ final Animator.AnimatorListener endListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ finalView.setAlpha(startAlpha);
+ // TODO: restore view offset from overlay repositioning
+ if (finalViewToKeep != null) {
+ finalViewToKeep.setVisibility(finalVisibility);
+ }
+ if (finalOverlayView != null) {
+ finalSceneRoot.getOverlay().remove(finalOverlayView);
+ }
+ }
+ };
+ return runAnimation(view, startAlpha, endAlpha, endListener);
}
if (viewToKeep != null) {
// TODO: find a different way to do this, like just changing the view to be
// VISIBLE for the duration of the transition
viewToKeep.setVisibility((View.VISIBLE));
- return true;
- }
- return false;
- }
-
- @Override
- protected Animator disappear(ViewGroup sceneRoot,
- TransitionValues startValues, int startVisibility,
- TransitionValues endValues, int endVisibility) {
- if ((mFadingMode & OUT) != OUT) {
- return null;
- }
- View startView = (startValues != null) ? startValues.view : null;
- View endView = (endValues != null) ? endValues.view : null;
- if (Transition.DBG) {
- Log.d(LOG_TAG, "Fade.disappear: startView, startVis, endView, endVis = " +
- startView + ", " + startVisibility + ", " + endView + ", " + endVisibility);
- }
- View view;
- View overlayView = null;
- View viewToKeep = null;
- final int finalVisibility = endVisibility;
- if (endView == null) {
- // view was removed: add the start view to the Overlay
- view = startView;
- overlayView = view;
- } else {
- // visibility change
- if (endVisibility == View.INVISIBLE) {
- view = endView;
- viewToKeep = view;
- } else {
- // Becoming GONE
- if (startView == endView) {
- view = endView;
- viewToKeep = view;
- } else {
- view = startView;
- overlayView = view;
+ // TODO: add automatic facility to Visibility superclass for keeping views around
+ final float startAlpha = view.getAlpha();
+ float endAlpha = 0;
+ final View finalView = view;
+ final View finalOverlayView = overlayView;
+ final View finalViewToKeep = viewToKeep;
+ final ViewGroup finalSceneRoot = sceneRoot;
+ final Animator.AnimatorListener endListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ finalView.setAlpha(startAlpha);
+ // TODO: restore view offset from overlay repositioning
+ if (finalViewToKeep != null) {
+ finalViewToKeep.setVisibility(finalVisibility);
+ }
+ if (finalOverlayView != null) {
+ finalSceneRoot.getOverlay().remove(finalOverlayView);
+ }
}
- }
+ };
+ return runAnimation(view, startAlpha, endAlpha, endListener);
}
- // TODO: add automatic facility to Visibility superclass for keeping views around
- final float startAlpha = view.getAlpha();
- float endAlpha = 0;
- final View finalView = view;
- final View finalOverlayView = overlayView;
- final View finalViewToKeep = viewToKeep;
- final ViewGroup finalSceneRoot = sceneRoot;
- final Animator.AnimatorListener endListener = new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- finalView.setAlpha(startAlpha);
- // TODO: restore view offset from overlay repositioning
- if (finalViewToKeep != null) {
- finalViewToKeep.setVisibility(finalVisibility);
- }
- if (finalOverlayView != null) {
- finalSceneRoot.getOverlay().remove(finalOverlayView);
- }
- }
- };
- return runAnimation(view, startAlpha, endAlpha, endListener);
+ return null;
}
} \ No newline at end of file
diff --git a/core/java/android/view/transition/Move.java b/core/java/android/view/transition/Move.java
index 5c9da88..ceda5a5 100644
--- a/core/java/android/view/transition/Move.java
+++ b/core/java/android/view/transition/Move.java
@@ -84,24 +84,21 @@ public class Move extends Transition {
if (startValues == null || endValues == null) {
return null;
}
- final View view = endValues.view;
- if (view.getParent() == null) {
- // TODO: Might want to make it possible to Move an disappearing view.
- // This workaround is here because if a parallel Fade is not running on the view
- // Then it won't get added to the hierarchy and the animator below will not fire,
- // causing the transition to not end
- return null;
- }
- // TODO: need to handle non-VG case?
- ViewGroup startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT);
- ViewGroup endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
+ Map<String, Object> startParentVals = startValues.values;
+ Map<String, Object> endParentVals = endValues.values;
+ ViewGroup startParent = (ViewGroup) startParentVals.get(PROPNAME_PARENT);
+ ViewGroup endParent = (ViewGroup) endParentVals.get(PROPNAME_PARENT);
if (startParent == null || endParent == null) {
return null;
}
+ final View view = endValues.view;
boolean parentsEqual = (startParent == endParent) ||
(startParent.getId() == endParent.getId());
+ // TODO: Might want reparenting to be separate/subclass transition, or at least
+ // triggered by a property on Move. Otherwise, we're forcing the requirement that
+ // all parents in layouts have IDs to avoid layout-inflation resulting in a side-effect
+ // of reparenting the views.
if (!mReparent || parentsEqual) {
- // Common case - view belongs to the same layout before/after. Just animate its bounds
Rect startBounds = (Rect) startValues.values.get(PROPNAME_BOUNDS);
Rect endBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS);
int startLeft = startBounds.left;
@@ -118,13 +115,6 @@ public class Move extends Transition {
int endHeight = endBottom - endTop;
int numChanges = 0;
if (startWidth != 0 && startHeight != 0 && endWidth != 0 && endHeight != 0) {
- if (Transition.DBG) {
- Log.v(LOG_TAG, "Target = " + endValues.view);
- Log.v(LOG_TAG, " start bounds: " + startLeft + ", " + startTop + ", " +
- startRight + ", " + startBottom);
- Log.v(LOG_TAG, " end bounds: " + endLeft + ", " + endTop + ", " +
- endRight + ", " + endBottom);
- }
if (startLeft != endLeft) ++numChanges;
if (startTop != endTop) ++numChanges;
if (startRight != endRight) ++numChanges;
@@ -134,6 +124,10 @@ public class Move extends Transition {
if (!mResizeClip) {
PropertyValuesHolder pvh[] = new PropertyValuesHolder[numChanges];
int pvhIndex = 0;
+ if (startLeft != endLeft) view.setLeft(startLeft);
+ if (startTop != endTop) view.setTop(startTop);
+ if (startRight != endRight) view.setRight(startRight);
+ if (startBottom != endBottom) view.setBottom(startBottom);
if (startLeft != endLeft) {
pvh[pvhIndex++] = PropertyValuesHolder.ofInt("left", startLeft, endLeft);
}
@@ -161,6 +155,13 @@ public class Move extends Transition {
}
return anim;
} else {
+ if (startWidth != endWidth) view.setRight(endLeft +
+ Math.max(startWidth, endWidth));
+ if (startHeight != endHeight) view.setBottom(endTop +
+ Math.max(startHeight, endHeight));
+ // TODO: don't clobber TX/TY
+ if (startLeft != endLeft) view.setTranslationX(startLeft - endLeft);
+ if (startTop != endTop) view.setTranslationY(startTop - endTop);
// Animate location with translationX/Y and size with clip bounds
float transXDelta = endLeft - startLeft;
float transYDelta = endTop - startTop;
@@ -207,71 +208,6 @@ public class Move extends Transition {
}
}
} else {
- return (ObjectAnimator) endValues.values.get("drawableAnim");
- }
- return null;
- }
-
- @Override
- protected boolean setup(final ViewGroup sceneRoot, TransitionValues startValues,
- TransitionValues endValues) {
- if (startValues == null || endValues == null) {
- return false;
- }
- Map<String, Object> startParentVals = startValues.values;
- Map<String, Object> endParentVals = endValues.values;
- ViewGroup startParent = (ViewGroup) startParentVals.get(PROPNAME_PARENT);
- ViewGroup endParent = (ViewGroup) endParentVals.get(PROPNAME_PARENT);
- if (startParent == null || endParent == null) {
- return false;
- }
- final View view = endValues.view;
- boolean parentsEqual = (startParent == endParent) ||
- (startParent.getId() == endParent.getId());
- // TODO: Might want reparenting to be separate/subclass transition, or at least
- // triggered by a property on Move. Otherwise, we're forcing the requirement that
- // all parents in layouts have IDs to avoid layout-inflation resulting in a side-effect
- // of reparenting the views.
- if (!mReparent || parentsEqual) {
- Rect startBounds = (Rect) startValues.values.get(PROPNAME_BOUNDS);
- Rect endBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS);
- int startLeft = startBounds.left;
- int endLeft = endBounds.left;
- int startTop = startBounds.top;
- int endTop = endBounds.top;
- int startRight = startBounds.right;
- int endRight = endBounds.right;
- int startBottom = startBounds.bottom;
- int endBottom = endBounds.bottom;
- int startWidth = startRight - startLeft;
- int startHeight = startBottom - startTop;
- int endWidth = endRight - endLeft;
- int endHeight = endBottom - endTop;
- int numChanges = 0;
- if (startWidth != 0 && startHeight != 0 && endWidth != 0 && endHeight != 0) {
- if (startLeft != endLeft) ++numChanges;
- if (startTop != endTop) ++numChanges;
- if (startRight != endRight) ++numChanges;
- if (startBottom != endBottom) ++numChanges;
- }
- if (numChanges > 0) {
- if (!mResizeClip) {
- if (startLeft != endLeft) view.setLeft(startLeft);
- if (startTop != endTop) view.setTop(startTop);
- if (startRight != endRight) view.setRight(startRight);
- if (startBottom != endBottom) view.setBottom(startBottom);
- } else {
- if (startWidth != endWidth) view.setRight(endLeft +
- Math.max(startWidth, endWidth));
- if (startHeight != endHeight) view.setBottom(endTop +
- Math.max(startHeight, endHeight));
- // TODO: don't clobber TX/TY
- if (startLeft != endLeft) view.setTranslationX(startLeft - endLeft);
- if (startTop != endTop) view.setTranslationY(startTop - endTop);
- }
- return true;
- }
- } else {
int startX = (Integer) startValues.values.get(PROPNAME_WINDOW_X);
int startY = (Integer) startValues.values.get(PROPNAME_WINDOW_Y);
int endX = (Integer) endValues.values.get(PROPNAME_WINDOW_X);
@@ -286,14 +222,14 @@ public class Move extends Transition {
final BitmapDrawable drawable = new BitmapDrawable(bitmap);
view.setVisibility(View.INVISIBLE);
sceneRoot.getOverlay().add(drawable);
- Rect startBounds = new Rect(startX - tempLocation[0], startY - tempLocation[1],
+ Rect startBounds1 = new Rect(startX - tempLocation[0], startY - tempLocation[1],
startX - tempLocation[0] + view.getWidth(),
startY - tempLocation[1] + view.getHeight());
- Rect endBounds = new Rect(endX - tempLocation[0], endY - tempLocation[1],
+ Rect endBounds1 = new Rect(endX - tempLocation[0], endY - tempLocation[1],
endX - tempLocation[0] + view.getWidth(),
endY - tempLocation[1] + view.getHeight());
ObjectAnimator anim = ObjectAnimator.ofObject(drawable, "bounds",
- sRectEvaluator, startBounds, endBounds);
+ sRectEvaluator, startBounds1, endBounds1);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -301,10 +237,9 @@ public class Move extends Transition {
view.setVisibility(View.VISIBLE);
}
});
- endParentVals.put("drawableAnim", anim);
- return true;
+ return anim;
}
}
- return false;
+ return null;
}
}
diff --git a/core/java/android/view/transition/Recolor.java b/core/java/android/view/transition/Recolor.java
index 2179960..e4858c4 100644
--- a/core/java/android/view/transition/Recolor.java
+++ b/core/java/android/view/transition/Recolor.java
@@ -51,10 +51,10 @@ public class Recolor extends Transition {
}
@Override
- protected boolean setup(ViewGroup sceneRoot, TransitionValues startValues,
+ protected Animator play(ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
if (startValues == null || endValues == null) {
- return false;
+ return null;
}
final View view = endValues.view;
Drawable startBackground = (Drawable) startValues.values.get(PROPNAME_BACKGROUND);
@@ -66,6 +66,8 @@ public class Recolor extends Transition {
if (startColor.getColor() != endColor.getColor()) {
endColor.setColor(startColor.getColor());
changed = true;
+ return ObjectAnimator.ofObject(endBackground, "color",
+ new ArgbEvaluator(), startColor.getColor(), endColor.getColor());
}
}
if (view instanceof TextView) {
@@ -75,46 +77,10 @@ public class Recolor extends Transition {
if (start != end) {
textView.setTextColor(end);
changed = true;
- }
- }
- return changed;
- }
-
- @Override
- protected Animator play(ViewGroup sceneRoot, TransitionValues startValues,
- TransitionValues endValues) {
- if (startValues == null || endValues == null) {
- return null;
- }
- ObjectAnimator anim = null;
- final View view = endValues.view;
- Map<String, Object> startVals = startValues.values;
- Map<String, Object> endVals = endValues.values;
- Drawable startBackground = (Drawable) startVals.get(PROPNAME_BACKGROUND);
- Drawable endBackground = (Drawable) endVals.get(PROPNAME_BACKGROUND);
- if (startBackground instanceof ColorDrawable && endBackground instanceof ColorDrawable) {
- ColorDrawable startColor = (ColorDrawable) startBackground;
- ColorDrawable endColor = (ColorDrawable) endBackground;
- if (startColor.getColor() != endColor.getColor()) {
- anim = ObjectAnimator.ofObject(endBackground, "color",
- new ArgbEvaluator(), startColor.getColor(), endColor.getColor());
- if (getStartDelay() > 0) {
- endColor.setColor(startColor.getColor());
- }
- }
- }
- if (view instanceof TextView) {
- TextView textView = (TextView) view;
- int start = (Integer) startValues.values.get(PROPNAME_TEXT_COLOR);
- int end = (Integer) endValues.values.get(PROPNAME_TEXT_COLOR);
- if (start != end) {
- anim = ObjectAnimator.ofObject(textView, "textColor",
+ return ObjectAnimator.ofObject(textView, "textColor",
new ArgbEvaluator(), start, end);
- if (getStartDelay() > 0) {
- textView.setTextColor(end);
- }
}
}
- return anim;
+ return null;
}
}
diff --git a/core/java/android/view/transition/Rotate.java b/core/java/android/view/transition/Rotate.java
index 8d579d2..d35a6dc7 100644
--- a/core/java/android/view/transition/Rotate.java
+++ b/core/java/android/view/transition/Rotate.java
@@ -35,22 +35,6 @@ public class Rotate extends Transition {
}
@Override
- protected boolean setup(ViewGroup sceneRoot, TransitionValues startValues,
- TransitionValues endValues) {
- if (startValues == null || endValues == null) {
- return false;
- }
- final View view = endValues.view;
- float startRotation = (Float) startValues.values.get(PROPNAME_ROTATION);
- float endRotation = (Float) endValues.values.get(PROPNAME_ROTATION);
- if (startRotation != endRotation) {
- view.setRotation(startRotation);
- return true;
- }
- return false;
- }
-
- @Override
protected Animator play(ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
if (startValues == null || endValues == null) {
@@ -60,6 +44,7 @@ public class Rotate extends Transition {
float startRotation = (Float) startValues.values.get(PROPNAME_ROTATION);
float endRotation = (Float) endValues.values.get(PROPNAME_ROTATION);
if (startRotation != endRotation) {
+ view.setRotation(startRotation);
return ObjectAnimator.ofFloat(view, View.ROTATION,
startRotation, endRotation);
}
diff --git a/core/java/android/view/transition/Slide.java b/core/java/android/view/transition/Slide.java
index e39daa6..b2f5db5 100644
--- a/core/java/android/view/transition/Slide.java
+++ b/core/java/android/view/transition/Slide.java
@@ -41,6 +41,7 @@ public class Slide extends Visibility {
TransitionValues startValues, int startVisibility,
TransitionValues endValues, int endVisibility) {
View endView = (endValues != null) ? endValues.view : null;
+ endView.setTranslationY(-2 * endView.getHeight());
ObjectAnimator anim = ObjectAnimator.ofFloat(endView, View.TRANSLATION_Y,
-2 * endView.getHeight(), 0);
anim.setInterpolator(sDecelerator);
@@ -48,28 +49,11 @@ public class Slide extends Visibility {
}
@Override
- protected boolean setupAppear(ViewGroup sceneRoot,
- TransitionValues startValues, int startVisibility,
- TransitionValues endValues, int endVisibility) {
- View endView = (endValues != null) ? endValues.view : null;
- endView.setTranslationY(-2 * endView.getHeight());
- return true;
- }
-
- @Override
- protected boolean setupDisappear(ViewGroup sceneRoot,
- TransitionValues startValues, int startVisibility,
- TransitionValues endValues, int endVisibility) {
- View startView = (startValues != null) ? startValues.view : null;
- startView.setTranslationY(0);
- return true;
- }
-
- @Override
protected Animator disappear(ViewGroup sceneRoot,
TransitionValues startValues, int startVisibility,
TransitionValues endValues, int endVisibility) {
View startView = (startValues != null) ? startValues.view : null;
+ startView.setTranslationY(0);
ObjectAnimator anim = ObjectAnimator.ofFloat(startView, View.TRANSLATION_Y, 0,
-2 * startView.getHeight());
anim.setInterpolator(sAccelerator);
diff --git a/core/java/android/view/transition/TextChange.java b/core/java/android/view/transition/TextChange.java
index 16e990f..f033e63 100644
--- a/core/java/android/view/transition/TextChange.java
+++ b/core/java/android/view/transition/TextChange.java
@@ -47,24 +47,6 @@ public class TextChange extends Transition {
}
@Override
- protected boolean setup(ViewGroup sceneRoot, TransitionValues startValues,
- TransitionValues endValues) {
- if (startValues == null || endValues == null || !(endValues.view instanceof TextView)) {
- return false;
- }
- final TextView view = (TextView) endValues.view;
- Map<String, Object> startVals = startValues.values;
- Map<String, Object> endVals = endValues.values;
- String startText = (String) startVals.get(PROPNAME_TEXT);
- String endText = (String) endVals.get(PROPNAME_TEXT);
- if (!startText.equals(endText)) {
- view.setText(startText);
- return true;
- }
- return false;
- }
-
- @Override
protected Animator play(ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
if (startValues == null || endValues == null || !(endValues.view instanceof TextView)) {
@@ -73,11 +55,10 @@ public class TextChange extends Transition {
final TextView view = (TextView) endValues.view;
Map<String, Object> startVals = startValues.values;
Map<String, Object> endVals = endValues.values;
- final String startText = (String) startVals.get(PROPNAME_TEXT);
+ String startText = (String) startVals.get(PROPNAME_TEXT);
final String endText = (String) endVals.get(PROPNAME_TEXT);
if (!startText.equals(endText)) {
- // This noop animation is just used to keep the text in its start state
- // until the transition ends
+ view.setText(startText);
ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
anim.addListener(new AnimatorListenerAdapter() {
@Override
diff --git a/core/java/android/view/transition/Transition.java b/core/java/android/view/transition/Transition.java
index fd12339..2cffd26 100644
--- a/core/java/android/view/transition/Transition.java
+++ b/core/java/android/view/transition/Transition.java
@@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
import android.util.ArrayMap;
import android.util.LongSparseArray;
+import android.util.Pair;
import android.util.SparseArray;
import android.view.SurfaceView;
import android.view.TextureView;
@@ -149,49 +150,32 @@ public abstract class Transition implements Cloneable {
/**
* This method is called by the transition's parent (all the way up to the
* topmost Transition in the hierarchy) with the sceneRoot and start/end
- * values that the transition may need to run animations on its target
- * views. The method is called for every applicable target object, which
- * is stored in the {@link TransitionValues#view} field. When the method
- * results in an animation needing to be run, the transition will construct
- * the appropriate {@link Animator} object and return it. The transition
- * mechanism will apply any applicable duration, startDelay, and interpolator
- * to that animation and start it. Returning null from the method tells the
- * transition engine that there is no animation to be played (TransitionGroup
- * will return null because any applicable animations were started on its child
- * transitions already and there is no animation to be run on the group itself).
- *
- * @param sceneRoot
- * @param startValues
- * @param endValues
- * @return Animator The animation to run.
- */
- protected abstract Animator play(ViewGroup sceneRoot, TransitionValues startValues,
- TransitionValues endValues);
-
- /**
- * This method is called by the transition's parent (all the way up to the
- * topmost Transition in the hierarchy) with the sceneRoot and start/end
- * values that the transition may need to set things up at the start of a
- * Transition. For example, if an overall Transition consists of several
+ * values that the transition may need to set up initial target values
+ * and construct an appropriate animation. For example, if an overall
+ * Transition is a {@link TransitionGroup} consisting of several
* child transitions in sequence, then some of the child transitions may
* want to set initial values on target views prior to the overall
- * Transition commencing, to put them in an appropriate scene for the
+ * Transition commencing, to put them in an appropriate state for the
* delay between that start and the child Transition start time. For
* example, a transition that fades an item in may wish to set the starting
* alpha value to 0, to avoid it blinking in prior to the transition
* actually starting the animation. This is necessary because the scene
* change that triggers the Transition will automatically set the end-scene
* on all target views, so a Transition that wants to animate from a
- * different value should set that value in the setup() method.
+ * different value should set that value prior to returning from this method.
*
* <p>Additionally, a Transition can perform logic to determine whether
* the transition needs to run on the given target and start/end values.
* For example, a transition that resizes objects on the screen may wish
* to avoid running for views which are not present in either the start
- * or end scenes. A return value of <code>false</code> indicates that
- * the transition should not run, and there will be no ensuing call to the
- * {@link #play(ViewGroup, TransitionValues, TransitionValues)} method during
- * this scene change. The default implementation returns true.</p>
+ * or end scenes. A return value of <code>null</code> indicates that
+ * no animation should run. The default implementation returns null.</p>
+ *
+ * <p>If there is an animator created and returned from this method, the
+ * transition mechanism will apply any applicable duration, startDelay,
+ * and interpolator to that animation and start it. A return value of
+ * <code>null</code> indicates that no animation should run. The default
+ * implementation returns null.</p>
*
* <p>The method is called for every applicable target object, which is
* stored in the {@link TransitionValues#view} field.</p>
@@ -199,31 +183,25 @@ public abstract class Transition implements Cloneable {
* @param sceneRoot
* @param startValues
* @param endValues
- * @return True if the Transition's {@link #play(ViewGroup,
- * TransitionValues, TransitionValues) play()} method should be called
- * during this scene change, false otherwise.
+ * @return A non-null Animator to be started at the appropriate time in the
+ * overall transition for this scene change, null otherwise.
*/
- protected boolean setup(ViewGroup sceneRoot, TransitionValues startValues,
+ protected Animator play(ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
- return true;
+ return null;
}
/**
- * This version of setup() is called with the entire set of start/end
+ * This version of play() is called with the entire set of start/end
* values. The implementation in Transition iterates through these lists
- * and calls {@link #setup(ViewGroup, TransitionValues, TransitionValues)}
+ * and calls {@link #play(ViewGroup, TransitionValues, TransitionValues)}
* with each set of start/end values on this transition. The
* TransitionGroup subclass overrides this method and delegates it to
- * each of its children in succession. The intention in splitting
- * setup() out from play() is to allow all Transitions in the tree to
- * set up the appropriate start scene for their target objects prior to
- * any calls to play(), which is necessary when there is a sequential
- * Transition, where a child transition which is not the first may want to
- * set up a target's scene prior to the overall Transition start.
+ * each of its children in succession.
*
* @hide
*/
- protected void setup(ViewGroup sceneRoot, TransitionValuesMaps startValues,
+ protected void play(ViewGroup sceneRoot, TransitionValuesMaps startValues,
TransitionValuesMaps endValues) {
mPlayStartValuesList.clear();
mPlayEndValuesList.clear();
@@ -335,7 +313,9 @@ public abstract class Transition implements Cloneable {
TransitionValues start = startValuesList.get(i);
TransitionValues end = endValuesList.get(i);
// TODO: what to do about targetIds and itemIds?
- if (setup(sceneRoot, start, end)) {
+ Animator animator = play(sceneRoot, start, end);
+ if (animator != null) {
+ mAnimatorMap.put(new Pair(start, end), animator);
// Note: we've already done the check against targetIDs in these lists
mPlayStartValuesList.add(start);
mPlayEndValuesList.add(end);
@@ -343,6 +323,9 @@ public abstract class Transition implements Cloneable {
}
}
+ ArrayMap<Pair<TransitionValues, TransitionValues>, Animator> mAnimatorMap =
+ new ArrayMap<Pair<TransitionValues, TransitionValues>, Animator>();
+
/**
* Internal utility method for checking whether a given view/id
* is valid for this transition, where "valid" means that either
@@ -375,16 +358,12 @@ public abstract class Transition implements Cloneable {
}
/**
- * This version of play() is called with the entire set of start/end
- * values. The implementation in Transition iterates through these lists
- * and calls {@link #play(ViewGroup, TransitionValues, TransitionValues)}
- * with each set of start/end values on this transition. The
- * TransitionGroup subclass overrides this method and delegates it to
- * each of its children in succession.
+ * This is called internally once all animations have been set up by the
+ * transition hierarchy. \
*
* @hide
*/
- protected void play(ViewGroup sceneRoot) {
+ protected void runAnimations() {
startTransition();
// Now walk the list of TransitionValues, calling play for each pair
@@ -392,10 +371,11 @@ public abstract class Transition implements Cloneable {
TransitionValues start = mPlayStartValuesList.get(i);
TransitionValues end = mPlayEndValuesList.get(i);
startTransition();
- runAnimator(play(sceneRoot, start, end));
+ runAnimator(mAnimatorMap.get(new Pair(start, end)));
}
mPlayStartValuesList.clear();
mPlayEndValuesList.clear();
+ mAnimatorMap.clear();
endTransition();
}
@@ -424,19 +404,18 @@ public abstract class Transition implements Cloneable {
* <code>start</code>. The main concern for an implementation is what the
* properties are that the transition cares about and what the values are
* for all of those properties. The start and end values will be compared
- * later during the setup() and play() methods to determine what, if any,
- * animations, should be run.
+ * later during the
+ * {@link #play(android.view.ViewGroup, TransitionValues, TransitionValues)}
+ * method to determine what, if any, animations, should be run.
*
- * @param transitionValues The holder any values that the Transition
- * wishes to store. Values are stored in the fields of this
- * TransitionValues object, according to their type, and are keyed from
- * a String value. For example, to start a view's rotation value,
- * a Transition might call
- * <code>transitionValues.floatValues.put("rotation", view.getRotation())
- * </code>. The target <code>View</code> will already be stored in
- * the transitionValues structure when this method is called. The other
- * fields in TransitionValues, e.g. <code>floatValues</code>,
- * may need to be instantiated if they have not yet been created.
+ * @param transitionValues The holder for any values that the Transition
+ * wishes to store. Values are stored in the <code>values</code> field
+ * of this TransitionValues object and are keyed from
+ * a String value. For example, to store a view's rotation value,
+ * a transition might call
+ * <code>transitionValues.values.put("appname:transitionname:rotation",
+ * view.getRotation())</code>. The target view will already be stored in
+ * the transitionValues structure when this method is called.
*/
protected abstract void captureValues(TransitionValues transitionValues, boolean start);
@@ -666,15 +645,15 @@ public abstract class Transition implements Cloneable {
/**
* Called by TransitionManager to play the transition. This calls
- * setup() and then play() with the full set of per-view
- * transitionValues objects
+ * play() to set things up and create all of the animations and then
+ * runAnimations() to actually start the animations.
*/
void playTransition(ViewGroup sceneRoot) {
// setup() must be called on entire transition hierarchy and set of views
// before calling play() on anything; every transition needs a chance to set up
// target views appropriately before transitions begin running
- setup(sceneRoot, mStartValues, mEndValues);
- play(sceneRoot);
+ play(sceneRoot, mStartValues, mEndValues);
+ runAnimations();
}
/**
diff --git a/core/java/android/view/transition/TransitionGroup.java b/core/java/android/view/transition/TransitionGroup.java
index 6f9a3ef..d0e61ea 100644
--- a/core/java/android/view/transition/TransitionGroup.java
+++ b/core/java/android/view/transition/TransitionGroup.java
@@ -16,9 +16,7 @@
package android.view.transition;
-import android.animation.Animator;
import android.util.AndroidRuntimeException;
-import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
@@ -187,10 +185,10 @@ public class TransitionGroup extends Transition {
* @hide
*/
@Override
- protected void setup(ViewGroup sceneRoot, TransitionValuesMaps startValues,
+ protected void play(ViewGroup sceneRoot, TransitionValuesMaps startValues,
TransitionValuesMaps endValues) {
for (Transition childTransition : mTransitions) {
- childTransition.setup(sceneRoot, startValues, endValues);
+ childTransition.play(sceneRoot, startValues, endValues);
}
}
@@ -198,9 +196,8 @@ public class TransitionGroup extends Transition {
* @hide
*/
@Override
- protected void play(ViewGroup sceneRoot) {
+ protected void runAnimations() {
setupStartEndListeners();
- final ViewGroup finalSceneRoot = sceneRoot;
if (!mPlayTogether) {
// Setup sequence with listeners
// TODO: Need to add listeners in such a way that we can remove them later if canceled
@@ -210,78 +207,23 @@ public class TransitionGroup extends Transition {
previousTransition.addListener(new TransitionListenerAdapter() {
@Override
public void onTransitionEnd(Transition transition) {
- nextTransition.play(finalSceneRoot);
+ nextTransition.runAnimations();
transition.removeListener(this);
}
});
}
Transition firstTransition = mTransitions.get(0);
if (firstTransition != null) {
- firstTransition.play(finalSceneRoot);
+ firstTransition.runAnimations();
}
} else {
for (Transition childTransition : mTransitions) {
- childTransition.play(finalSceneRoot);
+ childTransition.runAnimations();
}
}
}
@Override
- protected Animator play(ViewGroup sceneRoot,
- TransitionValues startValues, TransitionValues endValues) {
- final View view = (endValues != null) ? endValues.view :
- (startValues != null) ? startValues.view : null;
- final int targetId = (view != null) ? view.getId() : -1;
- // TODO: not sure this is a valid check - what about auto-targets? No need for ids.
- if (targetId < 0) {
- return null;
- }
- setupStartEndListeners();
- if (!mPlayTogether) {
- final ViewGroup finalSceneRoot = sceneRoot;
- final TransitionValues finalStartValues = startValues;
- final TransitionValues finalEndValues = endValues;
- // Setup sequence with listeners
- // TODO: Need to add listeners in such a way that we can remove them later if canceled
- for (int i = 1; i < mTransitions.size(); ++i) {
- Transition previousTransition = mTransitions.get(i - 1);
- final Transition nextTransition = mTransitions.get(i);
- previousTransition.addListener(new TransitionListenerAdapter() {
- @Override
- public void onTransitionEnd(Transition transition) {
- nextTransition.startTransition();
- if (nextTransition.isValidTarget(view, targetId)) {
- animate(nextTransition.play(finalSceneRoot, finalStartValues,
- finalEndValues));
- } else {
- nextTransition.endTransition();
- }
- }
- });
- }
- Transition firstTransition = mTransitions.get(0);
- if (firstTransition != null) {
- firstTransition.startTransition();
- if (firstTransition.isValidTarget(view, targetId)) {
- animate(firstTransition.play(finalSceneRoot, finalStartValues, finalEndValues));
- } else {
- firstTransition.endTransition();
- }
- }
- } else {
- for (Transition childTransition : mTransitions) {
- childTransition.startTransition();
- if (childTransition.isValidTarget(view, targetId)) {
- animate(childTransition.play(sceneRoot, startValues, endValues));
- } else {
- childTransition.endTransition();
- }
- }
- }
- return null;
- }
-
- @Override
protected void captureValues(TransitionValues transitionValues, boolean start) {
int targetId = transitionValues.view.getId();
for (Transition childTransition : mTransitions) {
diff --git a/core/java/android/view/transition/TransitionValues.java b/core/java/android/view/transition/TransitionValues.java
index 963e04d..f361666 100644
--- a/core/java/android/view/transition/TransitionValues.java
+++ b/core/java/android/view/transition/TransitionValues.java
@@ -36,9 +36,9 @@ import java.util.Map;
* {@link Transition#captureValues(TransitionValues, boolean)}
* capture} phases of a scene change, once when the start values are captured
* and again when the end values are captured. These start/end values are then
- * passed into the transitions during the play phase of the scene change,
- * for {@link Transition#setup(ViewGroup, TransitionValues, TransitionValues)} and
- * for {@link Transition#play(ViewGroup, TransitionValues, TransitionValues)}.</p>
+ * passed into the transitions via the
+ * for {@link Transition#play(ViewGroup, TransitionValues, TransitionValues)}
+ * method.</p>
*/
public class TransitionValues {
diff --git a/core/java/android/view/transition/Visibility.java b/core/java/android/view/transition/Visibility.java
index c9dba6b..6d39ab6 100644
--- a/core/java/android/view/transition/Visibility.java
+++ b/core/java/android/view/transition/Visibility.java
@@ -29,8 +29,8 @@ import android.view.ViewParent;
* utility for subclasses such as {@link Fade}, which use this visibility
* information to determine the specific animations to run when visibility
* changes occur. Subclasses should implement one or more of the methods
- * {@link #setupAppear(ViewGroup, TransitionValues, int, TransitionValues, int)},
- * {@link #setupDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)},
+ * {@link #appear(ViewGroup, TransitionValues, int, TransitionValues, int)},
+ * {@link #disappear(ViewGroup, TransitionValues, int, TransitionValues, int)},
* {@link #appear(ViewGroup, TransitionValues, int, TransitionValues, int)}, and
* {@link #disappear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
*/
@@ -139,7 +139,7 @@ public abstract class Visibility extends Transition {
}
@Override
- protected boolean setup(ViewGroup sceneRoot, TransitionValues startValues,
+ protected Animator play(ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues);
// Ensure not in parent hierarchy that's also becoming visible/invisible
@@ -149,32 +149,16 @@ public abstract class Visibility extends Transition {
if (parent != null) {
if (!isHierarchyVisibilityChanging(sceneRoot, parent)) {
if (visInfo.fadeIn) {
- return setupAppear(sceneRoot, startValues, visInfo.startVisibility,
+ return appear(sceneRoot, startValues, visInfo.startVisibility,
endValues, visInfo.endVisibility);
} else {
- return setupDisappear(sceneRoot, startValues, visInfo.startVisibility,
+ return disappear(sceneRoot, startValues, visInfo.startVisibility,
endValues, visInfo.endVisibility
);
}
}
}
}
- return false;
- }
-
- @Override
- protected Animator play(ViewGroup sceneRoot, TransitionValues startValues,
- TransitionValues endValues) {
- VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues);
- if (visInfo.visibilityChange) {
- if (visInfo.fadeIn) {
- return appear(sceneRoot, startValues, visInfo.startVisibility,
- endValues, visInfo.endVisibility);
- } else {
- return disappear(sceneRoot, startValues, visInfo.startVisibility,
- endValues, visInfo.endVisibility);
- }
- }
return null;
}
@@ -190,10 +174,10 @@ public abstract class Visibility extends Transition {
* @param endVisibility
* @return
*/
- protected boolean setupAppear(ViewGroup sceneRoot,
+ protected Animator appear(ViewGroup sceneRoot,
TransitionValues startValues, int startVisibility,
TransitionValues endValues, int endVisibility) {
- return true;
+ return null;
}
/**
@@ -208,38 +192,6 @@ public abstract class Visibility extends Transition {
* @param endVisibility
* @return
*/
- protected boolean setupDisappear(ViewGroup sceneRoot,
- TransitionValues startValues, int startVisibility,
- TransitionValues endValues, int endVisibility) {
- return true;
- }
-
- /**
- * The default implementation of this method does nothing. Subclasses
- * should override if they need to do anything when target objects
- * appear during the scene change.
- * @param sceneRoot
- * @param startValues
- * @param startVisibility
- * @param endValues
- * @param endVisibility
- */
- protected Animator appear(ViewGroup sceneRoot,
- TransitionValues startValues, int startVisibility,
- TransitionValues endValues, int endVisibility) {
- return null;
- }
-
- /**
- * The default implementation of this method does nothing. Subclasses
- * should override if they need to do anything when target objects
- * disappear during the scene change.
- * @param sceneRoot
- * @param startValues
- * @param startVisibility
- * @param endValues
- * @param endVisibility
- */
protected Animator disappear(ViewGroup sceneRoot,
TransitionValues startValues, int startVisibility,
TransitionValues endValues, int endVisibility) {
diff --git a/tests/TransitionTests/AndroidManifest.xml b/tests/TransitionTests/AndroidManifest.xml
index 3861164..5483f64 100644
--- a/tests/TransitionTests/AndroidManifest.xml
+++ b/tests/TransitionTests/AndroidManifest.xml
@@ -226,6 +226,13 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <activity android:label="HierarchicalMove"
+ android:name=".HierarchicalMove">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
</application>
diff --git a/tests/TransitionTests/res/layout/hierarchical_move.xml b/tests/TransitionTests/res/layout/hierarchical_move.xml
new file mode 100644
index 0000000..1e70ba9
--- /dev/null
+++ b/tests/TransitionTests/res/layout/hierarchical_move.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/submit"
+ android:onClick="sendMessage"
+ android:id="@+id/sceneSwitchButton"/>
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/button0"
+ android:id="@+id/button0"/>
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/button1"
+ android:id="@+id/button1"/>
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/button2"
+ android:id="@+id/button2"/>
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/button3"
+ android:id="@+id/button3"/>
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/button4"
+ android:id="@+id/button4"/>
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/button5"
+ android:id="@+id/button5"/>
+
+</LinearLayout> \ No newline at end of file
diff --git a/tests/TransitionTests/res/values/strings.xml b/tests/TransitionTests/res/values/strings.xml
index 3be243b..9b80a26 100644
--- a/tests/TransitionTests/res/values/strings.xml
+++ b/tests/TransitionTests/res/values/strings.xml
@@ -43,4 +43,10 @@
<string name="state2">State 2</string>
<string name="state3">State 3</string>
<string name="state4">State 4</string>
+ <string name="button0">Button 0</string>
+ <string name="button1">Button 1</string>
+ <string name="button2">Button 2</string>
+ <string name="button3">Button 3</string>
+ <string name="button4">Button 4</string>
+ <string name="button5">Button 5</string>
</resources>
diff --git a/tests/TransitionTests/src/com/android/transitiontests/HierarchicalMove.java b/tests/TransitionTests/src/com/android/transitiontests/HierarchicalMove.java
new file mode 100644
index 0000000..093d7c1
--- /dev/null
+++ b/tests/TransitionTests/src/com/android/transitiontests/HierarchicalMove.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+package com.android.transitiontests;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.transition.Move;
+import android.view.transition.Transition;
+import android.view.transition.TransitionGroup;
+import android.view.transition.TransitionManager;
+import android.widget.Button;
+
+import static android.widget.LinearLayout.LayoutParams;
+
+public class HierarchicalMove extends Activity {
+
+ Button[] buttons = new Button[6];
+ ViewGroup mSceneRoot;
+ boolean wide = false;
+ Transition mTransition;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.hierarchical_move);
+
+ View container = (View) findViewById(R.id.container);
+ mSceneRoot = (ViewGroup) container.getParent();
+
+ buttons[0] = (Button) findViewById(R.id.button0);
+ buttons[1] = (Button) findViewById(R.id.button1);
+ buttons[2] = (Button) findViewById(R.id.button2);
+ buttons[3] = (Button) findViewById(R.id.button3);
+ buttons[4] = (Button) findViewById(R.id.button4);
+ buttons[5] = (Button) findViewById(R.id.button5);
+
+ // Move button0, then buttons 1/2 together, then buttons 3/4/5 sequentially:
+ // group (seq)
+ // Move 0
+ // group (seq)
+ // group (together)
+ // Move 1
+ // Move 2
+ // group (sequentially)
+ // Move 3
+ // Move 4/5
+ TransitionGroup rootTransition = new TransitionGroup(TransitionGroup.SEQUENTIALLY);
+
+ // button0
+ Transition move0 = new Move();
+ move0.setTargets(buttons[0]);
+
+ // buttons 1/2/3/4/5
+ TransitionGroup group12345 = new TransitionGroup(TransitionGroup.SEQUENTIALLY);
+
+ // buttons 1/2
+ TransitionGroup group12 = new TransitionGroup(TransitionGroup.TOGETHER);
+ Move move1 = new Move();
+ move1.setTargets(buttons[1]);
+ Move move2 = new Move();
+ move2.setTargets(buttons[2]);
+ group12.addTransitions(move1, move2);
+
+ TransitionGroup group345 = new TransitionGroup(TransitionGroup.SEQUENTIALLY);
+ Move move3 = new Move();
+ move3.setTargets(buttons[3]);
+ Move move45 = new Move();
+ move45.setTargets(buttons[4], buttons[5]);
+ group345.addTransitions(move3, move45);
+
+ group12345.addTransitions(move0, group12, group345);
+
+ rootTransition.addTransitions(group12345);
+ rootTransition.setDuration(1000);
+ mTransition = rootTransition;
+
+ }
+
+ public void sendMessage(View view) {
+ TransitionManager.beginDelayedTransition(mSceneRoot, mTransition);
+ int widthSpec = wide ? LayoutParams.WRAP_CONTENT : LayoutParams.MATCH_PARENT;
+ LayoutParams params = new LayoutParams(widthSpec, LayoutParams.WRAP_CONTENT);
+ for (int i = 0; i < buttons.length; ++i) {
+ buttons[i].setLayoutParams(params);
+ }
+ wide = !wide;
+ }
+
+}