Loading api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -1978,6 +1978,7 @@ package android.animation { method public boolean isRunning(); method public void removeChild(android.view.ViewGroup, android.view.View); method public void removeTransitionListener(android.animation.LayoutTransition.TransitionListener); method public void setAnimateParentHierarchy(boolean); method public void setAnimator(int, android.animation.Animator); method public void setDuration(long); method public void setDuration(int, long); Loading Loading @@ -21441,6 +21442,8 @@ package android.view { method public void setScaleY(float); method public void setScrollBarStyle(int); method public void setScrollContainer(boolean); method public void setScrollX(int); method public void setScrollY(int); method public void setScrollbarFadingEnabled(boolean); method public void setSelected(boolean); method public void setSoundEffectsEnabled(boolean); core/java/android/animation/LayoutTransition.java +199 −115 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.animation; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.DecelerateInterpolator; Loading Loading @@ -70,8 +71,9 @@ import java.util.List; * moving as a result of the layout event) as well as the values that are changing (such as the * position and size of that object). The actual values that are pushed to each animation * depends on what properties are specified for the animation. For example, the default * CHANGE_APPEARING animation animates <code>left</code>, <code>top</code>, <code>right</code>, * and <code>bottom</code>. Values for these properties are updated with the pre- and post-layout * CHANGE_APPEARING animation animates the <code>left</code>, <code>top</code>, <code>right</code>, * <code>bottom</code>, <code>scrollX</code>, and <code>scrollY</code> properties. * Values for these properties are updated with the pre- and post-layout * values when the transition begins. Custom animations will be similarly populated with * the target and values being animated, assuming they use ObjectAnimator objects with * property names that are known on the target object.</p> Loading Loading @@ -210,6 +212,14 @@ public class LayoutTransition { */ private ArrayList<TransitionListener> mListeners; /** * Controls whether changing animations automatically animate the parent hierarchy as well. * This behavior prevents artifacts when wrap_content layouts snap to the end state as the * transition begins, causing visual glitches and clipping. * Default value is true. */ private boolean mAnimateParentHierarchy = true; /** * Constructs a LayoutTransition object. By default, the object will listen to layout Loading @@ -223,14 +233,17 @@ public class LayoutTransition { PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1); PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0, 1); PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 1); PropertyValuesHolder pvhScrollX = PropertyValuesHolder.ofInt("scrollX", 0, 1); PropertyValuesHolder pvhScrollY = PropertyValuesHolder.ofInt("scrollY", 0, 1); defaultChangeIn = ObjectAnimator.ofPropertyValuesHolder(this, pvhLeft, pvhTop, pvhRight, pvhBottom); pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScrollX, pvhScrollY); defaultChangeIn.setDuration(DEFAULT_DURATION); defaultChangeIn.setStartDelay(mChangingAppearingDelay); defaultChangeIn.setInterpolator(mChangingAppearingInterpolator); defaultChangeOut = defaultChangeIn.clone(); defaultChangeOut.setStartDelay(mChangingDisappearingDelay); defaultChangeOut.setInterpolator(mChangingDisappearingInterpolator); defaultFadeIn = ObjectAnimator.ofFloat(this, "alpha", 0f, 1f); defaultFadeIn.setDuration(DEFAULT_DURATION); defaultFadeIn.setStartDelay(mAppearingDelay); Loading Loading @@ -572,8 +585,62 @@ public class LayoutTransition { // only animate the views not being added or removed if (child != newView) { setupChangeAnimation(parent, changeReason, baseAnimator, duration, child); } } if (mAnimateParentHierarchy) { ViewGroup tempParent = parent; while (tempParent != null) { ViewParent parentParent = tempParent.getParent(); if (parentParent instanceof ViewGroup) { setupChangeAnimation((ViewGroup)parentParent, changeReason, baseAnimator, duration, tempParent); tempParent = (ViewGroup) parentParent; } else { tempParent = null; } } } // This is the cleanup step. When we get this rendering event, we know that all of // the appropriate animations have been set up and run. Now we can clear out the // layout listeners. observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() { parent.getViewTreeObserver().removeOnPreDrawListener(this); int numChildren = parent.getChildCount(); for (int i = 0; i < numChildren; ++i) { final View child = parent.getChildAt(i); child.removeOnLayoutChangeListener(layoutChangeListenerMap.get(child)); } layoutChangeListenerMap.clear(); return true; } }); } /** * This flag controls whether CHANGE_APPEARING or CHANGE_DISAPPEARING animations will * cause the same changing animation to be run on the parent hierarchy as well. This allows * containers of transitioning views to also transition, which may be necessary in situations * where the containers bounds change between the before/after states and may clip their * children during the transition animations. For example, layouts with wrap_content will * adjust their bounds according to the dimensions of their children. * * @param animateParentHierarchy A boolean value indicating whether the parents of * transitioning views should also be animated during the transition. Default value is true. */ public void setAnimateParentHierarchy(boolean animateParentHierarchy) { mAnimateParentHierarchy = animateParentHierarchy; } /** * Utility function called by runChangingTransition for both the children and the parent * hierarchy. */ private void setupChangeAnimation(final ViewGroup parent, final int changeReason, Animator baseAnimator, final long duration, final View child) { // Make a copy of the appropriate animation final Animator anim = baseAnimator.clone(); Loading Loading @@ -616,6 +683,24 @@ public class LayoutTransition { // Tell the animation to extract end values from the changed object anim.setupEndValues(); if (anim instanceof ValueAnimator) { boolean valuesDiffer = false; ValueAnimator valueAnim = (ValueAnimator)anim; PropertyValuesHolder[] oldValues = valueAnim.getValues(); for (int i = 0; i < oldValues.length; ++i) { PropertyValuesHolder pvh = oldValues[i]; KeyframeSet keyframeSet = pvh.mKeyframeSet; if (keyframeSet.mFirstKeyframe == null || keyframeSet.mLastKeyframe == null || !keyframeSet.mFirstKeyframe.getValue().equals( keyframeSet.mLastKeyframe.getValue())) { valuesDiffer = true; } } if (!valuesDiffer) { return; } } long startDelay; if (changeReason == APPEARING) { Loading @@ -639,10 +724,7 @@ public class LayoutTransition { // Cache the animation in case we need to cancel it later currentChangingAnimations.put(child, anim); if (anim instanceof ObjectAnimator) { ((ObjectAnimator) anim).setCurrentPlayTime(0); } anim.start(); parent.requestTransitionStart(LayoutTransition.this); // this only removes listeners whose views changed - must clear the // other listeners later Loading Loading @@ -687,22 +769,24 @@ public class LayoutTransition { // cache the listener for later removal layoutChangeListenerMap.put(child, listener); } /** * Starts the animations set up for a CHANGING transition. We separate the setup of these * animations from actually starting them, to avoid side-effects that starting the animations * may have on the properties of the affected objects. After setup, we tell the affected parent * that this transition should be started. The parent informs its ViewAncestor, which then * starts the transition after the current layout/measurement phase, just prior to drawing * the view hierarchy. * * @hide */ public void startChangingAnimations() { for (Animator anim : currentChangingAnimations.values()) { if (anim instanceof ObjectAnimator) { ((ObjectAnimator) anim).setCurrentPlayTime(0); } // This is the cleanup step. When we get this rendering event, we know that all of // the appropriate animations have been set up and run. Now we can clear out the // layout listeners. observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() { parent.getViewTreeObserver().removeOnPreDrawListener(this); int numChildren = parent.getChildCount(); for (int i = 0; i < numChildren; ++i) { final View child = parent.getChildAt(i); child.removeOnLayoutChangeListener(layoutChangeListenerMap.get(child)); } layoutChangeListenerMap.clear(); return true; anim.start(); } }); } /** Loading core/java/android/view/View.java +20 −0 Original line number Diff line number Diff line Loading @@ -6047,6 +6047,26 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility return mParent; } /** * Set the horizontal scrolled position of your view. This will cause a call to * {@link #onScrollChanged(int, int, int, int)} and the view will be * invalidated. * @param value the x position to scroll to */ public void setScrollX(int value) { scrollTo(value, mScrollY); } /** * Set the vertical scrolled position of your view. This will cause a call to * {@link #onScrollChanged(int, int, int, int)} and the view will be * invalidated. * @param value the y position to scroll to */ public void setScrollY(int value) { scrollTo(mScrollX, value); } /** * Return the scrolled left position of this view. This is the left edge of * the displayed part of your view. You do not need to draw any pixels Loading core/java/android/view/ViewAncestor.java +30 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.view; import android.Manifest; import android.animation.LayoutTransition; import android.app.ActivityManagerNative; import android.content.ClipDescription; import android.content.ComponentCallbacks; Loading Loading @@ -232,6 +233,7 @@ public final class ViewAncestor extends Handler implements ViewParent, long mResizeBitmapStartTime; int mResizeBitmapDuration; static final Interpolator mResizeInterpolator = new AccelerateDecelerateInterpolator(); private ArrayList<LayoutTransition> mPendingTransitions; final ViewConfiguration mViewConfiguration; Loading Loading @@ -700,6 +702,28 @@ public final class ViewAncestor extends Handler implements ViewParent, } } /** * Add LayoutTransition to the list of transitions to be started in the next traversal. * This list will be cleared after the transitions on the list are start()'ed. These * transitionsa re added by LayoutTransition itself when it sets up animations. The setup * happens during the layout phase of traversal, which we want to complete before any of the * animations are started (because those animations may side-effect properties that layout * depends upon, like the bounding rectangles of the affected views). So we add the transition * to the list and it is started just prior to starting the drawing phase of traversal. * * @param transition The LayoutTransition to be started on the next traversal. * * @hide */ public void requestTransitionStart(LayoutTransition transition) { if (mPendingTransitions == null || !mPendingTransitions.contains(transition)) { if (mPendingTransitions == null) { mPendingTransitions = new ArrayList<LayoutTransition>(); } mPendingTransitions.add(transition); } } private void performTraversals() { // cache mView since it is used so much below... final View host = mView; Loading Loading @@ -1395,6 +1419,12 @@ public final class ViewAncestor extends Handler implements ViewParent, boolean cancelDraw = attachInfo.mTreeObserver.dispatchOnPreDraw(); if (!cancelDraw && !newSurface) { if (mPendingTransitions != null && mPendingTransitions.size() > 0) { for (int i = 0; i < mPendingTransitions.size(); ++i) { mPendingTransitions.get(i).startChangingAnimations(); } mPendingTransitions.clear(); } mFullRedrawNeeded = false; final long drawStartTime; Loading core/java/android/view/ViewGroup.java +14 −0 Original line number Diff line number Diff line Loading @@ -4837,6 +4837,20 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager mAnimationListener = animationListener; } /** * This method is called by LayoutTransition when there are 'changing' animations that need * to start after the layout/setup phase. The request is forwarded to the ViewAncestor, who * starts all pending transitions prior to the drawing phase in the current traversal. * * @param transition The LayoutTransition to be started on the next traversal. * * @hide */ public void requestTransitionStart(LayoutTransition transition) { ViewAncestor viewAncestor = getViewAncestor(); viewAncestor.requestTransitionStart(transition); } /** * Return true if the pressed state should be delayed for children or descendants of this * ViewGroup. Generally, this should be done for containers that can scroll, such as a List. Loading Loading
api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -1978,6 +1978,7 @@ package android.animation { method public boolean isRunning(); method public void removeChild(android.view.ViewGroup, android.view.View); method public void removeTransitionListener(android.animation.LayoutTransition.TransitionListener); method public void setAnimateParentHierarchy(boolean); method public void setAnimator(int, android.animation.Animator); method public void setDuration(long); method public void setDuration(int, long); Loading Loading @@ -21441,6 +21442,8 @@ package android.view { method public void setScaleY(float); method public void setScrollBarStyle(int); method public void setScrollContainer(boolean); method public void setScrollX(int); method public void setScrollY(int); method public void setScrollbarFadingEnabled(boolean); method public void setSelected(boolean); method public void setSoundEffectsEnabled(boolean);
core/java/android/animation/LayoutTransition.java +199 −115 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.animation; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.DecelerateInterpolator; Loading Loading @@ -70,8 +71,9 @@ import java.util.List; * moving as a result of the layout event) as well as the values that are changing (such as the * position and size of that object). The actual values that are pushed to each animation * depends on what properties are specified for the animation. For example, the default * CHANGE_APPEARING animation animates <code>left</code>, <code>top</code>, <code>right</code>, * and <code>bottom</code>. Values for these properties are updated with the pre- and post-layout * CHANGE_APPEARING animation animates the <code>left</code>, <code>top</code>, <code>right</code>, * <code>bottom</code>, <code>scrollX</code>, and <code>scrollY</code> properties. * Values for these properties are updated with the pre- and post-layout * values when the transition begins. Custom animations will be similarly populated with * the target and values being animated, assuming they use ObjectAnimator objects with * property names that are known on the target object.</p> Loading Loading @@ -210,6 +212,14 @@ public class LayoutTransition { */ private ArrayList<TransitionListener> mListeners; /** * Controls whether changing animations automatically animate the parent hierarchy as well. * This behavior prevents artifacts when wrap_content layouts snap to the end state as the * transition begins, causing visual glitches and clipping. * Default value is true. */ private boolean mAnimateParentHierarchy = true; /** * Constructs a LayoutTransition object. By default, the object will listen to layout Loading @@ -223,14 +233,17 @@ public class LayoutTransition { PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1); PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0, 1); PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 1); PropertyValuesHolder pvhScrollX = PropertyValuesHolder.ofInt("scrollX", 0, 1); PropertyValuesHolder pvhScrollY = PropertyValuesHolder.ofInt("scrollY", 0, 1); defaultChangeIn = ObjectAnimator.ofPropertyValuesHolder(this, pvhLeft, pvhTop, pvhRight, pvhBottom); pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScrollX, pvhScrollY); defaultChangeIn.setDuration(DEFAULT_DURATION); defaultChangeIn.setStartDelay(mChangingAppearingDelay); defaultChangeIn.setInterpolator(mChangingAppearingInterpolator); defaultChangeOut = defaultChangeIn.clone(); defaultChangeOut.setStartDelay(mChangingDisappearingDelay); defaultChangeOut.setInterpolator(mChangingDisappearingInterpolator); defaultFadeIn = ObjectAnimator.ofFloat(this, "alpha", 0f, 1f); defaultFadeIn.setDuration(DEFAULT_DURATION); defaultFadeIn.setStartDelay(mAppearingDelay); Loading Loading @@ -572,8 +585,62 @@ public class LayoutTransition { // only animate the views not being added or removed if (child != newView) { setupChangeAnimation(parent, changeReason, baseAnimator, duration, child); } } if (mAnimateParentHierarchy) { ViewGroup tempParent = parent; while (tempParent != null) { ViewParent parentParent = tempParent.getParent(); if (parentParent instanceof ViewGroup) { setupChangeAnimation((ViewGroup)parentParent, changeReason, baseAnimator, duration, tempParent); tempParent = (ViewGroup) parentParent; } else { tempParent = null; } } } // This is the cleanup step. When we get this rendering event, we know that all of // the appropriate animations have been set up and run. Now we can clear out the // layout listeners. observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() { parent.getViewTreeObserver().removeOnPreDrawListener(this); int numChildren = parent.getChildCount(); for (int i = 0; i < numChildren; ++i) { final View child = parent.getChildAt(i); child.removeOnLayoutChangeListener(layoutChangeListenerMap.get(child)); } layoutChangeListenerMap.clear(); return true; } }); } /** * This flag controls whether CHANGE_APPEARING or CHANGE_DISAPPEARING animations will * cause the same changing animation to be run on the parent hierarchy as well. This allows * containers of transitioning views to also transition, which may be necessary in situations * where the containers bounds change between the before/after states and may clip their * children during the transition animations. For example, layouts with wrap_content will * adjust their bounds according to the dimensions of their children. * * @param animateParentHierarchy A boolean value indicating whether the parents of * transitioning views should also be animated during the transition. Default value is true. */ public void setAnimateParentHierarchy(boolean animateParentHierarchy) { mAnimateParentHierarchy = animateParentHierarchy; } /** * Utility function called by runChangingTransition for both the children and the parent * hierarchy. */ private void setupChangeAnimation(final ViewGroup parent, final int changeReason, Animator baseAnimator, final long duration, final View child) { // Make a copy of the appropriate animation final Animator anim = baseAnimator.clone(); Loading Loading @@ -616,6 +683,24 @@ public class LayoutTransition { // Tell the animation to extract end values from the changed object anim.setupEndValues(); if (anim instanceof ValueAnimator) { boolean valuesDiffer = false; ValueAnimator valueAnim = (ValueAnimator)anim; PropertyValuesHolder[] oldValues = valueAnim.getValues(); for (int i = 0; i < oldValues.length; ++i) { PropertyValuesHolder pvh = oldValues[i]; KeyframeSet keyframeSet = pvh.mKeyframeSet; if (keyframeSet.mFirstKeyframe == null || keyframeSet.mLastKeyframe == null || !keyframeSet.mFirstKeyframe.getValue().equals( keyframeSet.mLastKeyframe.getValue())) { valuesDiffer = true; } } if (!valuesDiffer) { return; } } long startDelay; if (changeReason == APPEARING) { Loading @@ -639,10 +724,7 @@ public class LayoutTransition { // Cache the animation in case we need to cancel it later currentChangingAnimations.put(child, anim); if (anim instanceof ObjectAnimator) { ((ObjectAnimator) anim).setCurrentPlayTime(0); } anim.start(); parent.requestTransitionStart(LayoutTransition.this); // this only removes listeners whose views changed - must clear the // other listeners later Loading Loading @@ -687,22 +769,24 @@ public class LayoutTransition { // cache the listener for later removal layoutChangeListenerMap.put(child, listener); } /** * Starts the animations set up for a CHANGING transition. We separate the setup of these * animations from actually starting them, to avoid side-effects that starting the animations * may have on the properties of the affected objects. After setup, we tell the affected parent * that this transition should be started. The parent informs its ViewAncestor, which then * starts the transition after the current layout/measurement phase, just prior to drawing * the view hierarchy. * * @hide */ public void startChangingAnimations() { for (Animator anim : currentChangingAnimations.values()) { if (anim instanceof ObjectAnimator) { ((ObjectAnimator) anim).setCurrentPlayTime(0); } // This is the cleanup step. When we get this rendering event, we know that all of // the appropriate animations have been set up and run. Now we can clear out the // layout listeners. observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() { parent.getViewTreeObserver().removeOnPreDrawListener(this); int numChildren = parent.getChildCount(); for (int i = 0; i < numChildren; ++i) { final View child = parent.getChildAt(i); child.removeOnLayoutChangeListener(layoutChangeListenerMap.get(child)); } layoutChangeListenerMap.clear(); return true; anim.start(); } }); } /** Loading
core/java/android/view/View.java +20 −0 Original line number Diff line number Diff line Loading @@ -6047,6 +6047,26 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility return mParent; } /** * Set the horizontal scrolled position of your view. This will cause a call to * {@link #onScrollChanged(int, int, int, int)} and the view will be * invalidated. * @param value the x position to scroll to */ public void setScrollX(int value) { scrollTo(value, mScrollY); } /** * Set the vertical scrolled position of your view. This will cause a call to * {@link #onScrollChanged(int, int, int, int)} and the view will be * invalidated. * @param value the y position to scroll to */ public void setScrollY(int value) { scrollTo(mScrollX, value); } /** * Return the scrolled left position of this view. This is the left edge of * the displayed part of your view. You do not need to draw any pixels Loading
core/java/android/view/ViewAncestor.java +30 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.view; import android.Manifest; import android.animation.LayoutTransition; import android.app.ActivityManagerNative; import android.content.ClipDescription; import android.content.ComponentCallbacks; Loading Loading @@ -232,6 +233,7 @@ public final class ViewAncestor extends Handler implements ViewParent, long mResizeBitmapStartTime; int mResizeBitmapDuration; static final Interpolator mResizeInterpolator = new AccelerateDecelerateInterpolator(); private ArrayList<LayoutTransition> mPendingTransitions; final ViewConfiguration mViewConfiguration; Loading Loading @@ -700,6 +702,28 @@ public final class ViewAncestor extends Handler implements ViewParent, } } /** * Add LayoutTransition to the list of transitions to be started in the next traversal. * This list will be cleared after the transitions on the list are start()'ed. These * transitionsa re added by LayoutTransition itself when it sets up animations. The setup * happens during the layout phase of traversal, which we want to complete before any of the * animations are started (because those animations may side-effect properties that layout * depends upon, like the bounding rectangles of the affected views). So we add the transition * to the list and it is started just prior to starting the drawing phase of traversal. * * @param transition The LayoutTransition to be started on the next traversal. * * @hide */ public void requestTransitionStart(LayoutTransition transition) { if (mPendingTransitions == null || !mPendingTransitions.contains(transition)) { if (mPendingTransitions == null) { mPendingTransitions = new ArrayList<LayoutTransition>(); } mPendingTransitions.add(transition); } } private void performTraversals() { // cache mView since it is used so much below... final View host = mView; Loading Loading @@ -1395,6 +1419,12 @@ public final class ViewAncestor extends Handler implements ViewParent, boolean cancelDraw = attachInfo.mTreeObserver.dispatchOnPreDraw(); if (!cancelDraw && !newSurface) { if (mPendingTransitions != null && mPendingTransitions.size() > 0) { for (int i = 0; i < mPendingTransitions.size(); ++i) { mPendingTransitions.get(i).startChangingAnimations(); } mPendingTransitions.clear(); } mFullRedrawNeeded = false; final long drawStartTime; Loading
core/java/android/view/ViewGroup.java +14 −0 Original line number Diff line number Diff line Loading @@ -4837,6 +4837,20 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager mAnimationListener = animationListener; } /** * This method is called by LayoutTransition when there are 'changing' animations that need * to start after the layout/setup phase. The request is forwarded to the ViewAncestor, who * starts all pending transitions prior to the drawing phase in the current traversal. * * @param transition The LayoutTransition to be started on the next traversal. * * @hide */ public void requestTransitionStart(LayoutTransition transition) { ViewAncestor viewAncestor = getViewAncestor(); viewAncestor.requestTransitionStart(transition); } /** * Return true if the pressed state should be delayed for children or descendants of this * ViewGroup. Generally, this should be done for containers that can scroll, such as a List. Loading