Loading api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -1002,6 +1002,7 @@ package android { field public static final int requiredForAllUsers = 16843728; // 0x10103d0 field public static final int requiresFadingEdge = 16843685; // 0x10103a5 field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364 field public static final int resizeClip = 16844033; // 0x1010501 field public static final int resizeMode = 16843619; // 0x1010363 field public static final int resizeable = 16843405; // 0x101028d field public static final int resource = 16842789; // 0x1010025 Loading Loading @@ -31316,6 +31317,7 @@ package android.transition { ctor public ChangeBounds(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); method public boolean getResizeClip(); method public deprecated void setReparent(boolean); method public void setResizeClip(boolean); } core/java/android/transition/ChangeBounds.java +208 −110 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.transition; import android.animation.AnimatorSet; import android.content.Context; import android.content.res.TypedArray; import android.graphics.PointF; import android.animation.Animator; Loading @@ -36,6 +37,8 @@ import android.util.Property; import android.view.View; import android.view.ViewGroup; import com.android.internal.R; import java.util.Map; /** Loading @@ -43,17 +46,20 @@ import java.util.Map; * the scene change and animates those changes during the transition. * * <p>A ChangeBounds transition can be described in a resource file by using the * tag <code>changeBounds</code>, along with the other standard * tag <code>changeBounds</code>, using its attributes of * {@link android.R.styleable#ChangeBounds} along with the other standard * attributes of {@link android.R.styleable#Transition}.</p> */ public class ChangeBounds extends Transition { private static final String PROPNAME_BOUNDS = "android:changeBounds:bounds"; private static final String PROPNAME_CLIP = "android:changeBounds:clip"; private static final String PROPNAME_PARENT = "android:changeBounds:parent"; private static final String PROPNAME_WINDOW_X = "android:changeBounds:windowX"; private static final String PROPNAME_WINDOW_Y = "android:changeBounds:windowY"; private static final String[] sTransitionProperties = { PROPNAME_BOUNDS, PROPNAME_CLIP, PROPNAME_PARENT, PROPNAME_WINDOW_X, PROPNAME_WINDOW_Y Loading Loading @@ -103,6 +109,57 @@ public class ChangeBounds extends Transition { } }; private static final Property<View, PointF> BOTTOM_RIGHT_ONLY_PROPERTY = new Property<View, PointF>(PointF.class, "bottomRight") { @Override public void set(View view, PointF bottomRight) { int left = view.getLeft(); int top = view.getTop(); int right = Math.round(bottomRight.x); int bottom = Math.round(bottomRight.y); view.setLeftTopRightBottom(left, top, right, bottom); } @Override public PointF get(View view) { return null; } }; private static final Property<View, PointF> TOP_LEFT_ONLY_PROPERTY = new Property<View, PointF>(PointF.class, "topLeft") { @Override public void set(View view, PointF topLeft) { int left = Math.round(topLeft.x); int top = Math.round(topLeft.y); int right = view.getRight(); int bottom = view.getBottom(); view.setLeftTopRightBottom(left, top, right, bottom); } @Override public PointF get(View view) { return null; } }; private static final Property<View, PointF> POSITION_PROPERTY = new Property<View, PointF>(PointF.class, "position") { @Override public void set(View view, PointF topLeft) { int left = Math.round(topLeft.x); int top = Math.round(topLeft.y); int right = left + view.getWidth(); int bottom = top + view.getHeight(); view.setLeftTopRightBottom(left, top, right, bottom); } @Override public PointF get(View view) { return null; } }; int[] tempLocation = new int[2]; boolean mResizeClip = false; boolean mReparent = false; Loading @@ -114,6 +171,11 @@ public class ChangeBounds extends Transition { public ChangeBounds(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ChangeBounds); boolean resizeClip = a.getBoolean(R.styleable.ChangeBounds_resizeClip, false); a.recycle(); setResizeClip(resizeClip); } @Override Loading @@ -121,10 +183,36 @@ public class ChangeBounds extends Transition { return sTransitionProperties; } /** * When <code>resizeClip</code> is true, ChangeBounds resizes the view using the clipBounds * instead of changing the dimensions of the view during the animation. When * <code>resizeClip</code> is false, ChangeBounds resizes the View by changing its dimensions. * * <p>When resizeClip is set to true, the clip bounds is modified by ChangeBounds. Therefore, * {@link android.transition.ChangeClipBounds} is not compatible with ChangeBounds * in this mode.</p> * * @param resizeClip Used to indicate whether the view bounds should be modified or the * clip bounds should be modified by ChangeBounds. * @see android.view.View#setClipBounds(android.graphics.Rect) * @attr ref android.R.styleable#ChangeBounds_resizeClip */ public void setResizeClip(boolean resizeClip) { mResizeClip = resizeClip; } /** * Returns true when the ChangeBounds will resize by changing the clip bounds during the * view animation or false when bounds are changed. The default value is false. * * @return true when the ChangeBounds will resize by changing the clip bounds during the * view animation or false when bounds are changed. The default value is false. * @attr ref android.R.styleable#ChangeBounds_resizeClip */ public boolean getResizeClip() { return mResizeClip; } /** * Setting this flag tells ChangeBounds to track the before/after parent * of every view using this transition. The flag is not enabled by Loading Loading @@ -153,6 +241,9 @@ public class ChangeBounds extends Transition { values.values.put(PROPNAME_WINDOW_X, tempLocation[0]); values.values.put(PROPNAME_WINDOW_Y, tempLocation[1]); } if (mResizeClip) { values.values.put(PROPNAME_CLIP, view.getClipBounds()); } } } Loading Loading @@ -196,27 +287,41 @@ public class ChangeBounds extends Transition { if (parentMatches(startParent, endParent)) { 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; final int startLeft = startBounds.left; final int endLeft = endBounds.left; final int startTop = startBounds.top; final int endTop = endBounds.top; final int startRight = startBounds.right; final int endRight = endBounds.right; final int startBottom = startBounds.bottom; final int endBottom = endBounds.bottom; final int startWidth = startRight - startLeft; final int startHeight = startBottom - startTop; final int endWidth = endRight - endLeft; final int endHeight = endBottom - endTop; Rect startClip = (Rect) startValues.values.get(PROPNAME_CLIP); Rect endClip = (Rect) endValues.values.get(PROPNAME_CLIP); int numChanges = 0; if ((startWidth != 0 && startHeight != 0) || (endWidth != 0 && endHeight != 0)) { if (startLeft != endLeft || startTop != endTop) ++numChanges; if (startRight != endRight || startBottom != endBottom) ++numChanges; } if ((startClip != null && !startClip.equals(endClip)) || (startClip == null && endClip != null)) { ++numChanges; } if (numChanges > 0) { Animator anim; if (!mResizeClip) { view.setLeftTopRightBottom(startLeft, startTop, startRight, startBottom); ViewBounds viewBounds = new ViewBounds(view); if (numChanges == 2) { if (startWidth == endWidth && startHeight == endHeight) { Path topLeftPath = getPathMotion().getPath(startLeft, startTop, endLeft, endTop); anim = ObjectAnimator.ofObject(view, POSITION_PROPERTY, null, topLeftPath); } else { final ViewBounds viewBounds = new ViewBounds(view); Path topLeftPath = getPathMotion().getPath(startLeft, startTop, endLeft, endTop); ObjectAnimator topLeftAnimator = ObjectAnimator Loading @@ -226,73 +331,73 @@ public class ChangeBounds extends Transition { endRight, endBottom); ObjectAnimator bottomRightAnimator = ObjectAnimator.ofObject(viewBounds, BOTTOM_RIGHT_PROPERTY, null, bottomRightPath); AnimatorSet anim = new AnimatorSet(); anim.playTogether(topLeftAnimator, bottomRightAnimator); AnimatorSet set = new AnimatorSet(); set.playTogether(topLeftAnimator, bottomRightAnimator); anim = set; set.addListener(new AnimatorListenerAdapter() { // We need a strong reference to viewBounds until the // animator ends. private ViewBounds mViewBounds = viewBounds; }); } } else if (startLeft != endLeft || startTop != endTop) { Path topLeftPath = getPathMotion().getPath(startLeft, startTop, endLeft, endTop); anim = ObjectAnimator.ofObject(view, TOP_LEFT_ONLY_PROPERTY, null, topLeftPath); } else { Path bottomRight = getPathMotion().getPath(startRight, startBottom, endRight, endBottom); anim = ObjectAnimator.ofObject(view, BOTTOM_RIGHT_ONLY_PROPERTY, null, bottomRight); } } else { int maxWidth = Math.max(startWidth, endWidth); int maxHeight = Math.max(startHeight, endHeight); if (view.getParent() instanceof ViewGroup) { final ViewGroup parent = (ViewGroup) view.getParent(); parent.suppressLayout(true); TransitionListener transitionListener = new TransitionListenerAdapter() { boolean mCanceled = false; view.setLeftTopRightBottom(startLeft, startTop, startLeft + maxWidth, startTop + maxHeight); @Override public void onTransitionCancel(Transition transition) { parent.suppressLayout(false); mCanceled = true; ObjectAnimator positionAnimator = null; if (startLeft != endLeft || startTop != endTop) { Path topLeftPath = getPathMotion().getPath(startLeft, startTop, endLeft, endTop); positionAnimator = ObjectAnimator.ofObject(view, POSITION_PROPERTY, null, topLeftPath); } @Override public void onTransitionEnd(Transition transition) { if (!mCanceled) { parent.suppressLayout(false); final Rect finalClip = endClip; if (startClip == null) { startClip = new Rect(0, 0, startWidth, startHeight); } if (endClip == null) { endClip = new Rect(0, 0, endWidth, endHeight); } ObjectAnimator clipAnimator = null; if (!startClip.equals(endClip)) { view.setClipBounds(startClip); clipAnimator = ObjectAnimator.ofObject(view, "clipBounds", sRectEvaluator, startClip, endClip); clipAnimator.addListener(new AnimatorListenerAdapter() { private boolean mIsCanceled; @Override public void onTransitionPause(Transition transition) { parent.suppressLayout(false); public void onAnimationCancel(Animator animation) { mIsCanceled = true; } @Override public void onTransitionResume(Transition transition) { parent.suppressLayout(true); } }; addListener(transitionListener); public void onAnimationEnd(Animator animation) { if (!mIsCanceled) { view.setClipBounds(finalClip); view.setLeftTopRightBottom(endLeft, endTop, endRight, endBottom); } 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; int widthDelta = endWidth - startWidth; int heightDelta = endHeight - startHeight; numChanges = 0; if (transXDelta != 0) numChanges++; if (transYDelta != 0) numChanges++; if (widthDelta != 0 || heightDelta != 0) numChanges++; ObjectAnimator translationAnimator = null; if (transXDelta != 0 || transYDelta != 0) { Path topLeftPath = getPathMotion().getPath(0, 0, transXDelta, transYDelta); translationAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, View.TRANSLATION_Y, topLeftPath); } ObjectAnimator clipAnimator = null; if (widthDelta != 0 || heightDelta != 0) { Rect tempStartBounds = new Rect(0, 0, startWidth, startHeight); Rect tempEndBounds = new Rect(0, 0, endWidth, endHeight); clipAnimator = ObjectAnimator.ofObject(view, "clipBounds", sRectEvaluator, tempStartBounds, tempEndBounds); }); } Animator anim = TransitionUtils.mergeAnimators(translationAnimator, anim = TransitionUtils.mergeAnimators(positionAnimator, clipAnimator); } if (view.getParent() instanceof ViewGroup) { final ViewGroup parent = (ViewGroup) view.getParent(); parent.suppressLayout(true); Loading Loading @@ -324,15 +429,8 @@ public class ChangeBounds extends Transition { }; addListener(transitionListener); } anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { view.setClipBounds(null); } }); return anim; } } } else { int startX = (Integer) startValues.values.get(PROPNAME_WINDOW_X); int startY = (Integer) startValues.values.get(PROPNAME_WINDOW_Y); Loading core/java/android/view/View.java +1 −1 Original line number Diff line number Diff line Loading @@ -15691,7 +15691,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, sizeChange(newWidth, newHeight, oldWidth, oldHeight); } if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) { if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) { // If we are visible, force the DRAWN bit to on so that // this invalidate will go through (at least to our parent). // This is because someone may have invalidated this view core/res/res/values/attrs.xml +11 −0 Original line number Diff line number Diff line Loading @@ -5702,6 +5702,17 @@ <attr name="reparent" format="boolean"/> </declare-styleable> <!-- Use <code>changeBounds</code>as the root tag of the XML resource that describes a {@link android.transition.ChangeBounds} transition. The attributes of the {@link android.R.styleable#Transition Transition} resource are available in addition to the specific attributes of ChangeBounds described here. --> <declare-styleable name="ChangeBounds"> <!-- Resize the view by adjusting the clipBounds rather than changing the dimensions of the view itself. The default value is false. --> <attr name="resizeClip" format="boolean"/> </declare-styleable> <!-- Use <code>transitionManager</code> as the root tag of the XML resource that describes a {@link android.transition.TransitionManager TransitionManager}. --> Loading core/res/res/values/public.xml +1 −0 Original line number Diff line number Diff line Loading @@ -2589,5 +2589,6 @@ <!-- @hide --> <public-padding type="attr" name="private_resource_pad" end="0x01010500" /> <public type="attr" name="resizeClip"/> </resources> Loading
api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -1002,6 +1002,7 @@ package android { field public static final int requiredForAllUsers = 16843728; // 0x10103d0 field public static final int requiresFadingEdge = 16843685; // 0x10103a5 field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364 field public static final int resizeClip = 16844033; // 0x1010501 field public static final int resizeMode = 16843619; // 0x1010363 field public static final int resizeable = 16843405; // 0x101028d field public static final int resource = 16842789; // 0x1010025 Loading Loading @@ -31316,6 +31317,7 @@ package android.transition { ctor public ChangeBounds(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); method public boolean getResizeClip(); method public deprecated void setReparent(boolean); method public void setResizeClip(boolean); }
core/java/android/transition/ChangeBounds.java +208 −110 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.transition; import android.animation.AnimatorSet; import android.content.Context; import android.content.res.TypedArray; import android.graphics.PointF; import android.animation.Animator; Loading @@ -36,6 +37,8 @@ import android.util.Property; import android.view.View; import android.view.ViewGroup; import com.android.internal.R; import java.util.Map; /** Loading @@ -43,17 +46,20 @@ import java.util.Map; * the scene change and animates those changes during the transition. * * <p>A ChangeBounds transition can be described in a resource file by using the * tag <code>changeBounds</code>, along with the other standard * tag <code>changeBounds</code>, using its attributes of * {@link android.R.styleable#ChangeBounds} along with the other standard * attributes of {@link android.R.styleable#Transition}.</p> */ public class ChangeBounds extends Transition { private static final String PROPNAME_BOUNDS = "android:changeBounds:bounds"; private static final String PROPNAME_CLIP = "android:changeBounds:clip"; private static final String PROPNAME_PARENT = "android:changeBounds:parent"; private static final String PROPNAME_WINDOW_X = "android:changeBounds:windowX"; private static final String PROPNAME_WINDOW_Y = "android:changeBounds:windowY"; private static final String[] sTransitionProperties = { PROPNAME_BOUNDS, PROPNAME_CLIP, PROPNAME_PARENT, PROPNAME_WINDOW_X, PROPNAME_WINDOW_Y Loading Loading @@ -103,6 +109,57 @@ public class ChangeBounds extends Transition { } }; private static final Property<View, PointF> BOTTOM_RIGHT_ONLY_PROPERTY = new Property<View, PointF>(PointF.class, "bottomRight") { @Override public void set(View view, PointF bottomRight) { int left = view.getLeft(); int top = view.getTop(); int right = Math.round(bottomRight.x); int bottom = Math.round(bottomRight.y); view.setLeftTopRightBottom(left, top, right, bottom); } @Override public PointF get(View view) { return null; } }; private static final Property<View, PointF> TOP_LEFT_ONLY_PROPERTY = new Property<View, PointF>(PointF.class, "topLeft") { @Override public void set(View view, PointF topLeft) { int left = Math.round(topLeft.x); int top = Math.round(topLeft.y); int right = view.getRight(); int bottom = view.getBottom(); view.setLeftTopRightBottom(left, top, right, bottom); } @Override public PointF get(View view) { return null; } }; private static final Property<View, PointF> POSITION_PROPERTY = new Property<View, PointF>(PointF.class, "position") { @Override public void set(View view, PointF topLeft) { int left = Math.round(topLeft.x); int top = Math.round(topLeft.y); int right = left + view.getWidth(); int bottom = top + view.getHeight(); view.setLeftTopRightBottom(left, top, right, bottom); } @Override public PointF get(View view) { return null; } }; int[] tempLocation = new int[2]; boolean mResizeClip = false; boolean mReparent = false; Loading @@ -114,6 +171,11 @@ public class ChangeBounds extends Transition { public ChangeBounds(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ChangeBounds); boolean resizeClip = a.getBoolean(R.styleable.ChangeBounds_resizeClip, false); a.recycle(); setResizeClip(resizeClip); } @Override Loading @@ -121,10 +183,36 @@ public class ChangeBounds extends Transition { return sTransitionProperties; } /** * When <code>resizeClip</code> is true, ChangeBounds resizes the view using the clipBounds * instead of changing the dimensions of the view during the animation. When * <code>resizeClip</code> is false, ChangeBounds resizes the View by changing its dimensions. * * <p>When resizeClip is set to true, the clip bounds is modified by ChangeBounds. Therefore, * {@link android.transition.ChangeClipBounds} is not compatible with ChangeBounds * in this mode.</p> * * @param resizeClip Used to indicate whether the view bounds should be modified or the * clip bounds should be modified by ChangeBounds. * @see android.view.View#setClipBounds(android.graphics.Rect) * @attr ref android.R.styleable#ChangeBounds_resizeClip */ public void setResizeClip(boolean resizeClip) { mResizeClip = resizeClip; } /** * Returns true when the ChangeBounds will resize by changing the clip bounds during the * view animation or false when bounds are changed. The default value is false. * * @return true when the ChangeBounds will resize by changing the clip bounds during the * view animation or false when bounds are changed. The default value is false. * @attr ref android.R.styleable#ChangeBounds_resizeClip */ public boolean getResizeClip() { return mResizeClip; } /** * Setting this flag tells ChangeBounds to track the before/after parent * of every view using this transition. The flag is not enabled by Loading Loading @@ -153,6 +241,9 @@ public class ChangeBounds extends Transition { values.values.put(PROPNAME_WINDOW_X, tempLocation[0]); values.values.put(PROPNAME_WINDOW_Y, tempLocation[1]); } if (mResizeClip) { values.values.put(PROPNAME_CLIP, view.getClipBounds()); } } } Loading Loading @@ -196,27 +287,41 @@ public class ChangeBounds extends Transition { if (parentMatches(startParent, endParent)) { 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; final int startLeft = startBounds.left; final int endLeft = endBounds.left; final int startTop = startBounds.top; final int endTop = endBounds.top; final int startRight = startBounds.right; final int endRight = endBounds.right; final int startBottom = startBounds.bottom; final int endBottom = endBounds.bottom; final int startWidth = startRight - startLeft; final int startHeight = startBottom - startTop; final int endWidth = endRight - endLeft; final int endHeight = endBottom - endTop; Rect startClip = (Rect) startValues.values.get(PROPNAME_CLIP); Rect endClip = (Rect) endValues.values.get(PROPNAME_CLIP); int numChanges = 0; if ((startWidth != 0 && startHeight != 0) || (endWidth != 0 && endHeight != 0)) { if (startLeft != endLeft || startTop != endTop) ++numChanges; if (startRight != endRight || startBottom != endBottom) ++numChanges; } if ((startClip != null && !startClip.equals(endClip)) || (startClip == null && endClip != null)) { ++numChanges; } if (numChanges > 0) { Animator anim; if (!mResizeClip) { view.setLeftTopRightBottom(startLeft, startTop, startRight, startBottom); ViewBounds viewBounds = new ViewBounds(view); if (numChanges == 2) { if (startWidth == endWidth && startHeight == endHeight) { Path topLeftPath = getPathMotion().getPath(startLeft, startTop, endLeft, endTop); anim = ObjectAnimator.ofObject(view, POSITION_PROPERTY, null, topLeftPath); } else { final ViewBounds viewBounds = new ViewBounds(view); Path topLeftPath = getPathMotion().getPath(startLeft, startTop, endLeft, endTop); ObjectAnimator topLeftAnimator = ObjectAnimator Loading @@ -226,73 +331,73 @@ public class ChangeBounds extends Transition { endRight, endBottom); ObjectAnimator bottomRightAnimator = ObjectAnimator.ofObject(viewBounds, BOTTOM_RIGHT_PROPERTY, null, bottomRightPath); AnimatorSet anim = new AnimatorSet(); anim.playTogether(topLeftAnimator, bottomRightAnimator); AnimatorSet set = new AnimatorSet(); set.playTogether(topLeftAnimator, bottomRightAnimator); anim = set; set.addListener(new AnimatorListenerAdapter() { // We need a strong reference to viewBounds until the // animator ends. private ViewBounds mViewBounds = viewBounds; }); } } else if (startLeft != endLeft || startTop != endTop) { Path topLeftPath = getPathMotion().getPath(startLeft, startTop, endLeft, endTop); anim = ObjectAnimator.ofObject(view, TOP_LEFT_ONLY_PROPERTY, null, topLeftPath); } else { Path bottomRight = getPathMotion().getPath(startRight, startBottom, endRight, endBottom); anim = ObjectAnimator.ofObject(view, BOTTOM_RIGHT_ONLY_PROPERTY, null, bottomRight); } } else { int maxWidth = Math.max(startWidth, endWidth); int maxHeight = Math.max(startHeight, endHeight); if (view.getParent() instanceof ViewGroup) { final ViewGroup parent = (ViewGroup) view.getParent(); parent.suppressLayout(true); TransitionListener transitionListener = new TransitionListenerAdapter() { boolean mCanceled = false; view.setLeftTopRightBottom(startLeft, startTop, startLeft + maxWidth, startTop + maxHeight); @Override public void onTransitionCancel(Transition transition) { parent.suppressLayout(false); mCanceled = true; ObjectAnimator positionAnimator = null; if (startLeft != endLeft || startTop != endTop) { Path topLeftPath = getPathMotion().getPath(startLeft, startTop, endLeft, endTop); positionAnimator = ObjectAnimator.ofObject(view, POSITION_PROPERTY, null, topLeftPath); } @Override public void onTransitionEnd(Transition transition) { if (!mCanceled) { parent.suppressLayout(false); final Rect finalClip = endClip; if (startClip == null) { startClip = new Rect(0, 0, startWidth, startHeight); } if (endClip == null) { endClip = new Rect(0, 0, endWidth, endHeight); } ObjectAnimator clipAnimator = null; if (!startClip.equals(endClip)) { view.setClipBounds(startClip); clipAnimator = ObjectAnimator.ofObject(view, "clipBounds", sRectEvaluator, startClip, endClip); clipAnimator.addListener(new AnimatorListenerAdapter() { private boolean mIsCanceled; @Override public void onTransitionPause(Transition transition) { parent.suppressLayout(false); public void onAnimationCancel(Animator animation) { mIsCanceled = true; } @Override public void onTransitionResume(Transition transition) { parent.suppressLayout(true); } }; addListener(transitionListener); public void onAnimationEnd(Animator animation) { if (!mIsCanceled) { view.setClipBounds(finalClip); view.setLeftTopRightBottom(endLeft, endTop, endRight, endBottom); } 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; int widthDelta = endWidth - startWidth; int heightDelta = endHeight - startHeight; numChanges = 0; if (transXDelta != 0) numChanges++; if (transYDelta != 0) numChanges++; if (widthDelta != 0 || heightDelta != 0) numChanges++; ObjectAnimator translationAnimator = null; if (transXDelta != 0 || transYDelta != 0) { Path topLeftPath = getPathMotion().getPath(0, 0, transXDelta, transYDelta); translationAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, View.TRANSLATION_Y, topLeftPath); } ObjectAnimator clipAnimator = null; if (widthDelta != 0 || heightDelta != 0) { Rect tempStartBounds = new Rect(0, 0, startWidth, startHeight); Rect tempEndBounds = new Rect(0, 0, endWidth, endHeight); clipAnimator = ObjectAnimator.ofObject(view, "clipBounds", sRectEvaluator, tempStartBounds, tempEndBounds); }); } Animator anim = TransitionUtils.mergeAnimators(translationAnimator, anim = TransitionUtils.mergeAnimators(positionAnimator, clipAnimator); } if (view.getParent() instanceof ViewGroup) { final ViewGroup parent = (ViewGroup) view.getParent(); parent.suppressLayout(true); Loading Loading @@ -324,15 +429,8 @@ public class ChangeBounds extends Transition { }; addListener(transitionListener); } anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { view.setClipBounds(null); } }); return anim; } } } else { int startX = (Integer) startValues.values.get(PROPNAME_WINDOW_X); int startY = (Integer) startValues.values.get(PROPNAME_WINDOW_Y); Loading
core/java/android/view/View.java +1 −1 Original line number Diff line number Diff line Loading @@ -15691,7 +15691,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, sizeChange(newWidth, newHeight, oldWidth, oldHeight); } if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) { if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) { // If we are visible, force the DRAWN bit to on so that // this invalidate will go through (at least to our parent). // This is because someone may have invalidated this view
core/res/res/values/attrs.xml +11 −0 Original line number Diff line number Diff line Loading @@ -5702,6 +5702,17 @@ <attr name="reparent" format="boolean"/> </declare-styleable> <!-- Use <code>changeBounds</code>as the root tag of the XML resource that describes a {@link android.transition.ChangeBounds} transition. The attributes of the {@link android.R.styleable#Transition Transition} resource are available in addition to the specific attributes of ChangeBounds described here. --> <declare-styleable name="ChangeBounds"> <!-- Resize the view by adjusting the clipBounds rather than changing the dimensions of the view itself. The default value is false. --> <attr name="resizeClip" format="boolean"/> </declare-styleable> <!-- Use <code>transitionManager</code> as the root tag of the XML resource that describes a {@link android.transition.TransitionManager TransitionManager}. --> Loading
core/res/res/values/public.xml +1 −0 Original line number Diff line number Diff line Loading @@ -2589,5 +2589,6 @@ <!-- @hide --> <public-padding type="attr" name="private_resource_pad" end="0x01010500" /> <public type="attr" name="resizeClip"/> </resources>