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

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

Merge "Fixed ChangeBounds matching against the wrong View." into lmp-dev

parents 55e9affe 4d1ecf5d
Loading
Loading
Loading
Loading
+19 −12
Original line number Diff line number Diff line
@@ -16,13 +16,11 @@

package android.transition;

import android.animation.TypeConverter;
import android.content.Context;
import android.graphics.PointF;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.RectEvaluator;
@@ -119,10 +117,12 @@ public class ChangeBounds extends Transition {
        values.values.put(PROPNAME_BOUNDS, new Rect(view.getLeft(), view.getTop(),
                view.getRight(), view.getBottom()));
        values.values.put(PROPNAME_PARENT, values.view.getParent());
        if (mReparent) {
            values.view.getLocationInWindow(tempLocation);
            values.values.put(PROPNAME_WINDOW_X, tempLocation[0]);
            values.values.put(PROPNAME_WINDOW_Y, tempLocation[1]);
        }
    }

    @Override
    public void captureStartValues(TransitionValues transitionValues) {
@@ -134,6 +134,19 @@ public class ChangeBounds extends Transition {
        captureValues(transitionValues);
    }

    private boolean parentMatches(View startParent, View endParent) {
        boolean parentMatches = true;
        if (mReparent) {
            TransitionValues endValues = getMatchedTransitionValues(startParent, true);
            if (endValues == null) {
                parentMatches = startParent == endParent;
            } else {
                parentMatches = endParent == endValues.view;
            }
        }
        return parentMatches;
    }

    @Override
    public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
            TransitionValues endValues) {
@@ -148,13 +161,7 @@ public class ChangeBounds extends Transition {
            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 ChangeBounds. 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) {
        if (parentMatches(startParent, endParent)) {
            Rect startBounds = (Rect) startValues.values.get(PROPNAME_BOUNDS);
            Rect endBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS);
            int startLeft = startBounds.left;
+87 −52
Original line number Diff line number Diff line
@@ -192,6 +192,8 @@ public abstract class Transition implements Cloneable {
    private TransitionValuesMaps mEndValues = new TransitionValuesMaps();
    TransitionSet mParent = null;
    private int[] mMatchOrder = DEFAULT_MATCH_ORDER;
    ArrayList<TransitionValues> mStartValuesList; // only valid after playTransition starts
    ArrayList<TransitionValues> mEndValuesList; // only valid after playTransitions starts

    // Per-animator information used for later canceling when future transitions overlap
    private static ThreadLocal<ArrayMap<Animator, AnimationInfo>> sRunningAnimators =
@@ -518,32 +520,28 @@ public abstract class Transition implements Cloneable {
    }

    /**
     * Match start/end values by View instance. Adds matched values to startValuesList
     * and endValuesList and removes them from unmatchedStart and unmatchedEnd.
     * Match start/end values by View instance. Adds matched values to mStartValuesList
     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd.
     */
    private void matchInstances(ArrayList<TransitionValues> startValuesList,
            ArrayList<TransitionValues> endValuesList,
            ArrayMap<View, TransitionValues> unmatchedStart,
    private void matchInstances(ArrayMap<View, TransitionValues> unmatchedStart,
            ArrayMap<View, TransitionValues> unmatchedEnd) {
        for (int i = unmatchedStart.size() - 1; i >= 0; i--) {
            View view = unmatchedStart.keyAt(i);
            TransitionValues end = unmatchedEnd.remove(view);
            if (end != null) {
                TransitionValues start = unmatchedStart.removeAt(i);
                startValuesList.add(start);
                endValuesList.add(end);
                mStartValuesList.add(start);
                mEndValuesList.add(end);
            }
        }
    }

    /**
     * Match start/end values by Adapter item ID. Adds matched values to startValuesList
     * and endValuesList and removes them from unmatchedStart and unmatchedEnd, using
     * Match start/end values by Adapter item ID. Adds matched values to mStartValuesList
     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
     * startItemIds and endItemIds as a guide for which Views have unique item IDs.
     */
    private void matchItemIds(ArrayList<TransitionValues> startValuesList,
            ArrayList<TransitionValues> endValuesList,
            ArrayMap<View, TransitionValues> unmatchedStart,
    private void matchItemIds(ArrayMap<View, TransitionValues> unmatchedStart,
            ArrayMap<View, TransitionValues> unmatchedEnd,
            LongSparseArray<View> startItemIds, LongSparseArray<View> endItemIds) {
        int numStartIds = startItemIds.size();
@@ -555,8 +553,8 @@ public abstract class Transition implements Cloneable {
                    TransitionValues startValues = unmatchedStart.get(startView);
                    TransitionValues endValues = unmatchedEnd.get(endView);
                    if (startValues != null && endValues != null) {
                        startValuesList.add(startValues);
                        endValuesList.add(endValues);
                        mStartValuesList.add(startValues);
                        mEndValuesList.add(endValues);
                        unmatchedStart.remove(startView);
                        unmatchedEnd.remove(endView);
                    }
@@ -566,13 +564,11 @@ public abstract class Transition implements Cloneable {
    }

    /**
     * Match start/end values by Adapter view ID. Adds matched values to startValuesList
     * and endValuesList and removes them from unmatchedStart and unmatchedEnd, using
     * Match start/end values by Adapter view ID. Adds matched values to mStartValuesList
     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
     * startIds and endIds as a guide for which Views have unique IDs.
     */
    private void matchIds(ArrayList<TransitionValues> startValuesList,
            ArrayList<TransitionValues> endValuesList,
            ArrayMap<View, TransitionValues> unmatchedStart,
    private void matchIds(ArrayMap<View, TransitionValues> unmatchedStart,
            ArrayMap<View, TransitionValues> unmatchedEnd,
            SparseArray<View> startIds, SparseArray<View> endIds) {
        int numStartIds = startIds.size();
@@ -584,8 +580,8 @@ public abstract class Transition implements Cloneable {
                    TransitionValues startValues = unmatchedStart.get(startView);
                    TransitionValues endValues = unmatchedEnd.get(endView);
                    if (startValues != null && endValues != null) {
                        startValuesList.add(startValues);
                        endValuesList.add(endValues);
                        mStartValuesList.add(startValues);
                        mEndValuesList.add(endValues);
                        unmatchedStart.remove(startView);
                        unmatchedEnd.remove(endView);
                    }
@@ -595,13 +591,11 @@ public abstract class Transition implements Cloneable {
    }

    /**
     * Match start/end values by Adapter transitionName. Adds matched values to startValuesList
     * and endValuesList and removes them from unmatchedStart and unmatchedEnd, using
     * Match start/end values by Adapter transitionName. Adds matched values to mStartValuesList
     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
     * startNames and endNames as a guide for which Views have unique transitionNames.
     */
    private void matchNames(ArrayList<TransitionValues> startValuesList,
            ArrayList<TransitionValues> endValuesList,
            ArrayMap<View, TransitionValues> unmatchedStart,
    private void matchNames(ArrayMap<View, TransitionValues> unmatchedStart,
            ArrayMap<View, TransitionValues> unmatchedEnd,
            ArrayMap<String, View> startNames, ArrayMap<String, View> endNames) {
        int numStartNames = startNames.size();
@@ -613,8 +607,8 @@ public abstract class Transition implements Cloneable {
                    TransitionValues startValues = unmatchedStart.get(startView);
                    TransitionValues endValues = unmatchedEnd.get(endView);
                    if (startValues != null && endValues != null) {
                        startValuesList.add(startValues);
                        endValuesList.add(endValues);
                        mStartValuesList.add(startValues);
                        mEndValuesList.add(endValues);
                        unmatchedStart.remove(startView);
                        unmatchedEnd.remove(endView);
                    }
@@ -624,30 +618,26 @@ public abstract class Transition implements Cloneable {
    }

    /**
     * Adds all values from unmatchedStart and unmatchedEnd to startValuesList and endValuesList,
     * Adds all values from unmatchedStart and unmatchedEnd to mStartValuesList and mEndValuesList,
     * assuming that there is no match between values in the list.
     */
    private void addUnmatched(ArrayList<TransitionValues> startValuesList,
            ArrayList<TransitionValues> endValuesList,
            ArrayMap<View, TransitionValues> unmatchedStart,
    private void addUnmatched(ArrayMap<View, TransitionValues> unmatchedStart,
            ArrayMap<View, TransitionValues> unmatchedEnd) {
        // Views that only exist in the start Scene
        for (int i = 0; i < unmatchedStart.size(); i++) {
            startValuesList.add(unmatchedStart.valueAt(i));
            endValuesList.add(null);
            mStartValuesList.add(unmatchedStart.valueAt(i));
            mEndValuesList.add(null);
        }

        // Views that only exist in the end Scene
        for (int i = 0; i < unmatchedEnd.size(); i++) {
            endValuesList.add(unmatchedEnd.valueAt(i));
            startValuesList.add(null);
            mEndValuesList.add(unmatchedEnd.valueAt(i));
            mStartValuesList.add(null);
        }
    }

    private void matchStartAndEnd(TransitionValuesMaps startValues,
            TransitionValuesMaps endValues,
            ArrayList<TransitionValues> startValuesList,
            ArrayList<TransitionValues> endValuesList) {
            TransitionValuesMaps endValues) {
        ArrayMap<View, TransitionValues> unmatchedStart =
                new ArrayMap<View, TransitionValues>(startValues.viewValues);
        ArrayMap<View, TransitionValues> unmatchedEnd =
@@ -656,23 +646,23 @@ public abstract class Transition implements Cloneable {
        for (int i = 0; i < mMatchOrder.length; i++) {
            switch (mMatchOrder[i]) {
                case MATCH_INSTANCE:
                    matchInstances(startValuesList, endValuesList, unmatchedStart, unmatchedEnd);
                    matchInstances(unmatchedStart, unmatchedEnd);
                    break;
                case MATCH_NAME:
                    matchNames(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
                    matchNames(unmatchedStart, unmatchedEnd,
                            startValues.nameValues, endValues.nameValues);
                    break;
                case MATCH_ID:
                    matchIds(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
                    matchIds(unmatchedStart, unmatchedEnd,
                            startValues.idValues, endValues.idValues);
                    break;
                case MATCH_ITEM_ID:
                    matchItemIds(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
                    matchItemIds(unmatchedStart, unmatchedEnd,
                            startValues.itemIdValues, endValues.itemIdValues);
                    break;
            }
        }
        addUnmatched(startValuesList, endValuesList, unmatchedStart, unmatchedEnd);
        addUnmatched(unmatchedStart, unmatchedEnd);
    }

    /**
@@ -687,19 +677,17 @@ public abstract class Transition implements Cloneable {
     * @hide
     */
    protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
            TransitionValuesMaps endValues) {
            TransitionValuesMaps endValues, ArrayList<TransitionValues> startValuesList,
            ArrayList<TransitionValues> endValuesList) {
        if (DBG) {
            Log.d(LOG_TAG, "createAnimators() for " + this);
        }
        ArrayList<TransitionValues> startValuesList = new ArrayList<TransitionValues>();
        ArrayList<TransitionValues> endValuesList = new ArrayList<TransitionValues>();
        matchStartAndEnd(startValues, endValues, startValuesList, endValuesList);

        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
        long minStartDelay = Long.MAX_VALUE;
        int minAnimator = mAnimators.size();
        SparseLongArray startDelays = new SparseLongArray();
        for (int i = 0; i < startValuesList.size(); ++i) {
        int startValuesListCount = startValuesList.size();
        for (int i = 0; i < startValuesListCount; ++i) {
            TransitionValues start = startValuesList.get(i);
            TransitionValues end = endValuesList.get(i);
            // Only bother trying to animate with valid values that differ between start/end
@@ -1523,11 +1511,13 @@ public abstract class Transition implements Cloneable {
            mStartValues.idValues.clear();
            mStartValues.itemIdValues.clear();
            mStartValues.nameValues.clear();
            mStartValuesList = null;
        } else {
            mEndValues.viewValues.clear();
            mEndValues.idValues.clear();
            mEndValues.itemIdValues.clear();
            mEndValues.nameValues.clear();
            mEndValuesList = null;
        }
    }

@@ -1612,6 +1602,45 @@ public abstract class Transition implements Cloneable {
        return valuesMaps.viewValues.get(view);
    }

    /**
     * Find the matched start or end value for a given View. This is only valid
     * after playTransition starts. For example, it will be valid in
     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}, but not
     * in {@link #captureStartValues(TransitionValues)}.
     *
     * @param view The view to find the match for.
     * @param viewInStart Is View from the start values or end values.
     * @return The matching TransitionValues for view in either start or end values, depending
     * on viewInStart or null if there is no match for the given view.
     */
    TransitionValues getMatchedTransitionValues(View view, boolean viewInStart) {
        if (mParent != null) {
            return mParent.getMatchedTransitionValues(view, viewInStart);
        }
        ArrayList<TransitionValues> lookIn = viewInStart ? mStartValuesList : mEndValuesList;
        if (lookIn == null) {
            return null;
        }
        int count = lookIn.size();
        int index = -1;
        for (int i = 0; i < count; i++) {
            TransitionValues values = lookIn.get(i);
            if (values == null) {
                return null;
            }
            if (values.view == view) {
                index = i;
                break;
            }
        }
        TransitionValues values = null;
        if (index >= 0) {
            ArrayList<TransitionValues> matchIn = viewInStart ? mEndValuesList : mStartValuesList;
            values = matchIn.get(index);
        }
        return values;
    }

    /**
     * Pauses this transition, sending out calls to {@link
     * TransitionListener#onTransitionPause(Transition)} to all listeners
@@ -1684,6 +1713,10 @@ public abstract class Transition implements Cloneable {
     * runAnimations() to actually start the animations.
     */
    void playTransition(ViewGroup sceneRoot) {
        mStartValuesList = new ArrayList<TransitionValues>();
        mEndValuesList = new ArrayList<TransitionValues>();
        matchStartAndEnd(mStartValues, mEndValues);

        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
        int numOldAnims = runningAnimators.size();
        WindowId windowId = sceneRoot.getWindowId();
@@ -1694,7 +1727,7 @@ public abstract class Transition implements Cloneable {
                if (oldInfo != null && oldInfo.view != null && oldInfo.windowId == windowId) {
                    TransitionValues oldValues = oldInfo.values;
                    View oldView = oldInfo.view;
                    TransitionValues newValues = mEndValues.viewValues.get(oldView);
                    TransitionValues newValues = getMatchedTransitionValues(oldView, true);
                    boolean cancel = oldInfo.transition.areValuesChanged(oldValues, newValues);
                    if (cancel) {
                        if (anim.isRunning() || anim.isStarted()) {
@@ -1713,7 +1746,7 @@ public abstract class Transition implements Cloneable {
            }
        }

        createAnimators(sceneRoot, mStartValues, mEndValues);
        createAnimators(sceneRoot, mStartValues, mEndValues, mStartValuesList, mEndValuesList);
        runAnimators();
    }

@@ -2055,6 +2088,8 @@ public abstract class Transition implements Cloneable {
            clone.mAnimators = new ArrayList<Animator>();
            clone.mStartValues = new TransitionValuesMaps();
            clone.mEndValues = new TransitionValuesMaps();
            clone.mStartValuesList = null;
            clone.mEndValuesList = null;
        } catch (CloneNotSupportedException e) {}

        return clone;
+4 −2
Original line number Diff line number Diff line
@@ -386,11 +386,13 @@ public class TransitionSet extends Transition {
     */
    @Override
    protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
            TransitionValuesMaps endValues) {
            TransitionValuesMaps endValues, ArrayList<TransitionValues> startValuesList,
            ArrayList<TransitionValues> endValuesList) {
        startValues = removeExcludes(startValues);
        endValues = removeExcludes(endValues);
        for (Transition childTransition : mTransitions) {
            childTransition.createAnimators(sceneRoot, startValues, endValues);
            childTransition.createAnimators(sceneRoot, startValues, endValues, startValuesList,
                    endValuesList);
        }
    }