diff options
-rw-r--r-- | api/current.txt | 13 | ||||
-rw-r--r-- | core/java/android/view/transition/Crossfade.java | 126 | ||||
-rw-r--r-- | core/java/android/view/transition/Fade.java | 124 | ||||
-rw-r--r-- | core/java/android/view/transition/Move.java | 115 | ||||
-rw-r--r-- | core/java/android/view/transition/Recolor.java | 46 | ||||
-rw-r--r-- | core/java/android/view/transition/Rotate.java | 17 | ||||
-rw-r--r-- | core/java/android/view/transition/Slide.java | 20 | ||||
-rw-r--r-- | core/java/android/view/transition/TextChange.java | 23 | ||||
-rw-r--r-- | core/java/android/view/transition/Transition.java | 117 | ||||
-rw-r--r-- | core/java/android/view/transition/TransitionGroup.java | 70 | ||||
-rw-r--r-- | core/java/android/view/transition/TransitionValues.java | 6 | ||||
-rw-r--r-- | core/java/android/view/transition/Visibility.java | 62 | ||||
-rw-r--r-- | tests/TransitionTests/AndroidManifest.xml | 7 | ||||
-rw-r--r-- | tests/TransitionTests/res/layout/hierarchical_move.xml | 46 | ||||
-rw-r--r-- | tests/TransitionTests/res/values/strings.xml | 6 | ||||
-rw-r--r-- | tests/TransitionTests/src/com/android/transitiontests/HierarchicalMove.java | 104 |
16 files changed, 365 insertions, 537 deletions
diff --git a/api/current.txt b/api/current.txt index 481521e2498e..7281d011bf12 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 1e9b6fa56ca8..7cfba7087b2d 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 f3a4a392a1e9..3c5b6fad622e 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 5c9da887819a..ceda5a5f6f6e 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 217996059ad1..e4858c4d0a11 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 8d579d2b8cdf..d35a6dc745e5 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 e39daa6c0806..b2f5db5ea522 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 16e990fd58b4..f033e633b30c 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 fd12339485c9..2cffd268940a 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 6f9a3ef06dfb..d0e61ea28c4b 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 963e04dac1e8..f36166655df6 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 c9dba6bfff19..6d39ab650d28 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 3861164717f5..5483f6490948 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 000000000000..1e70ba96d062 --- /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 3be243bbcdd4..9b80a265e1ad 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 000000000000..093d7c1931a0 --- /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; + } + +} |