Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03d5c6f5 authored by George Mount's avatar George Mount Committed by Android (Google) Code Review
Browse files

Merge "Add resizeClip attribute to ChangeBounds." into lmp-mr1-dev

parents 088260d3 b7573c2d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
@@ -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);
  }
+208 −110
Original line number Diff line number Diff line
@@ -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;
@@ -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;

/**
@@ -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
@@ -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;
@@ -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
@@ -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
@@ -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());
            }
        }
    }

@@ -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
@@ -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);
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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
+11 −0
Original line number Diff line number Diff line
@@ -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}. -->
+1 −0
Original line number Diff line number Diff line
@@ -2589,5 +2589,6 @@

    <!-- @hide -->
    <public-padding type="attr" name="private_resource_pad" end="0x01010500" />
    <public type="attr" name="resizeClip"/>

</resources>