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

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

Merge "Allow changing order of matching Views in Transitions."

parents 4f8beae9 7b75062f
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -796,6 +796,7 @@ package android {
    field public static final int manageSpaceActivity = 16842756; // 0x1010004
    field public static final int mapViewStyle = 16842890; // 0x101008a
    field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
    field public static final int matchOrder = 16843861; // 0x1010455
    field public static final int max = 16843062; // 0x1010136
    field public static final int maxDate = 16843584; // 0x1010340
    field public static final int maxEms = 16843095; // 0x1010157
@@ -29362,8 +29363,13 @@ package android.transition {
    method public android.transition.Transition setDuration(long);
    method public void setEpicenterCallback(android.transition.Transition.EpicenterCallback);
    method public android.transition.Transition setInterpolator(android.animation.TimeInterpolator);
    method public void setMatchOrder(int...);
    method public void setPropagation(android.transition.TransitionPropagation);
    method public android.transition.Transition setStartDelay(long);
    field public static final int MATCH_ID = 3; // 0x3
    field public static final int MATCH_INSTANCE = 1; // 0x1
    field public static final int MATCH_ITEM_ID = 4; // 0x4
    field public static final int MATCH_VIEW_NAME = 2; // 0x2
  }
  public static abstract class Transition.EpicenterCallback {
+114 −14
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import android.util.ArrayMap;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import android.view.SurfaceView;
import android.view.TextureView;
@@ -108,6 +107,40 @@ public abstract class Transition implements Cloneable {
    private static final String LOG_TAG = "Transition";
    static final boolean DBG = false;

    /**
     * With {@link #setMatchOrder(int...)}, chooses to match by View instance.
     */
    public static final int MATCH_INSTANCE = 0x1;
    private static final int MATCH_FIRST = MATCH_INSTANCE;

    /**
     * With {@link #setMatchOrder(int...)}, chooses to match by
     * {@link android.view.View#getViewName()}. Null names will not be matched.
     */
    public static final int MATCH_VIEW_NAME = 0x2;

    /**
     * With {@link #setMatchOrder(int...)}, chooses to match by
     * {@link android.view.View#getId()}. Negative IDs will not be matched.
     */
    public static final int MATCH_ID = 0x3;

    /**
     * With {@link #setMatchOrder(int...)}, chooses to match by the {@link android.widget.Adapter}
     * item id. When {@link android.widget.Adapter#hasStableIds()} returns false, no match
     * will be made for items.
     */
    public static final int MATCH_ITEM_ID = 0x4;

    private static final int MATCH_LAST = MATCH_ITEM_ID;

    private static final int[] DEFAULT_MATCH_ORDER = {
        MATCH_VIEW_NAME,
        MATCH_INSTANCE,
        MATCH_ID,
        MATCH_ITEM_ID,
    };

    private String mName = getClass().getName();

    long mStartDelay = -1;
@@ -127,6 +160,7 @@ public abstract class Transition implements Cloneable {
    private TransitionValuesMaps mStartValues = new TransitionValuesMaps();
    private TransitionValuesMaps mEndValues = new TransitionValuesMaps();
    TransitionSet mParent = null;
    private int[] mMatchOrder = DEFAULT_MATCH_ORDER;

    // Per-animator information used for later canceling when future transitions overlap
    private static ThreadLocal<ArrayMap<Animator, AnimationInfo>> sRunningAnimators =
@@ -337,6 +371,53 @@ public abstract class Transition implements Cloneable {
        return null;
    }

    /**
     * Sets the order in which Transition matches View start and end values.
     * <p>
     * The default behavior is to match first by {@link android.view.View#getViewName()},
     * then by View instance, then by {@link android.view.View#getId()} and finally
     * by its item ID if it is in a direct child of ListView. The caller can
     * choose to have only some or all of the values of {@link #MATCH_INSTANCE},
     * {@link #MATCH_VIEW_NAME}, {@link #MATCH_ITEM_ID}, and {@link #MATCH_ID}. Only
     * the match algorithms supplied will be used to determine whether Views are the
     * the same in both the start and end Scene. Views that do not match will be considered
     * as entering or leaving the Scene.
     * </p>
     * @param matches A list of zero or more of {@link #MATCH_INSTANCE},
     *                {@link #MATCH_VIEW_NAME}, {@link #MATCH_ITEM_ID}, and {@link #MATCH_ID}.
     *                If none are provided, then the default match order will be set.
     */
    public void setMatchOrder(int... matches) {
        if (matches == null || matches.length == 0) {
            mMatchOrder = DEFAULT_MATCH_ORDER;
        } else {
            for (int i = 0; i < matches.length; i++) {
                int match = matches[i];
                if (!isValidMatch(match)) {
                    throw new IllegalArgumentException("matches contains invalid value");
                }
                if (alreadyContains(matches, i)) {
                    throw new IllegalArgumentException("matches contains a duplicate value");
                }
            }
            mMatchOrder = matches.clone();
        }
    }

    private static boolean isValidMatch(int match) {
        return (match >= MATCH_FIRST && match <= MATCH_LAST);
    }

    private static boolean alreadyContains(int[] array, int searchIndex) {
        int value = array[searchIndex];
        for (int i = 0; i < searchIndex; i++) {
            if (array[i] == value) {
                return true;
            }
        }
        return false;
    }

    /**
     * Match start/end values by View instance. Adds matched values to startValuesList
     * and endValuesList and removes them from unmatchedStart and unmatchedEnd.
@@ -464,6 +545,37 @@ public abstract class Transition implements Cloneable {
        }
    }

    private void matchStartAndEnd(TransitionValuesMaps startValues,
            TransitionValuesMaps endValues,
            ArrayList<TransitionValues> startValuesList,
            ArrayList<TransitionValues> endValuesList) {
        ArrayMap<View, TransitionValues> unmatchedStart =
                new ArrayMap<View, TransitionValues>(startValues.viewValues);
        ArrayMap<View, TransitionValues> unmatchedEnd =
                new ArrayMap<View, TransitionValues>(endValues.viewValues);

        for (int i = 0; i < mMatchOrder.length; i++) {
            switch (mMatchOrder[i]) {
                case MATCH_INSTANCE:
                    matchInstances(startValuesList, endValuesList, unmatchedStart, unmatchedEnd);
                    break;
                case MATCH_VIEW_NAME:
                    matchNames(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
                            startValues.nameValues, endValues.nameValues);
                    break;
                case MATCH_ID:
                    matchIds(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
                            startValues.idValues, endValues.idValues);
                    break;
                case MATCH_ITEM_ID:
                    matchItemIds(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
                            startValues.itemIdValues, endValues.itemIdValues);
                    break;
            }
        }
        addUnmatched(startValuesList, endValuesList, unmatchedStart, unmatchedEnd);
    }

    /**
     * This method, essentially a wrapper around all calls to createAnimator for all
     * possible target views, is called with the entire set of start/end
@@ -480,21 +592,9 @@ public abstract class Transition implements Cloneable {
        if (DBG) {
            Log.d(LOG_TAG, "createAnimators() for " + this);
        }
        ArrayMap<View, TransitionValues> unmatchedStart =
                new ArrayMap<View, TransitionValues>(startValues.viewValues);
        ArrayMap<View, TransitionValues> unmatchedEnd =
                new ArrayMap<View, TransitionValues>(endValues.viewValues);

        ArrayList<TransitionValues> startValuesList = new ArrayList<TransitionValues>();
        ArrayList<TransitionValues> endValuesList = new ArrayList<TransitionValues>();
        matchNames(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
                startValues.nameValues, endValues.nameValues);
        matchInstances(startValuesList, endValuesList, unmatchedStart, unmatchedEnd);
        matchIds(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
                startValues.idValues, endValues.idValues);
        matchItemIds(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
                startValues.itemIdValues, endValues.itemIdValues);
        addUnmatched(startValuesList, endValuesList, unmatchedStart, unmatchedEnd);
        matchStartAndEnd(startValues, endValues, startValuesList, endValuesList);

        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
        long minStartDelay = Long.MAX_VALUE;
+37 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;

/**
 * This class inflates scenes and transitions from resource files.
@@ -40,6 +41,10 @@ import java.util.ArrayList;
 * and {@link android.R.styleable#TransitionManager}.
 */
public class TransitionInflater {
    private static final String MATCH_INSTANCE = "instance";
    private static final String MATCH_VIEW_NAME = "viewName";
    private static final String MATCH_ID = "id";
    private static final String MATCH_ITEM_ID = "itemId";

    private Context mContext;

@@ -266,6 +271,33 @@ public class TransitionInflater {
        }
    }

    private int[] parseMatchOrder(String matchOrderString) {
        StringTokenizer st = new StringTokenizer(matchOrderString, ",");
        int matches[] = new int[st.countTokens()];
        int index = 0;
        while (st.hasMoreTokens()) {
            String token = st.nextToken().trim();
            if (MATCH_ID.equalsIgnoreCase(token)) {
                matches[index] = Transition.MATCH_ID;
            } else if (MATCH_INSTANCE.equalsIgnoreCase(token)) {
                matches[index] = Transition.MATCH_INSTANCE;
            } else if (MATCH_VIEW_NAME.equalsIgnoreCase(token)) {
                matches[index] = Transition.MATCH_VIEW_NAME;
            } else if (MATCH_ITEM_ID.equalsIgnoreCase(token)) {
                matches[index] = Transition.MATCH_ITEM_ID;
            } else if (token.isEmpty()) {
                int[] smallerMatches = new int[matches.length - 1];
                System.arraycopy(matches, 0, smallerMatches, 0, index);
                matches = smallerMatches;
                index--;
            } else {
                throw new RuntimeException("Unknown match type in matchOrder: '" + token + "'");
            }
            index++;
        }
        return matches;
    }

    private Transition loadTransition(Transition transition, AttributeSet attrs)
            throws Resources.NotFoundException {

@@ -284,6 +316,11 @@ public class TransitionInflater {
        if (resID > 0) {
            transition.setInterpolator(AnimationUtils.loadInterpolator(mContext, resID));
        }
        String matchOrder =
                a.getString(com.android.internal.R.styleable.Transition_matchOrder);
        if (matchOrder != null) {
            transition.setMatchOrder(parseMatchOrder(matchOrder));
        }
        a.recycle();
        return transition;
    }
+9 −0
Original line number Diff line number Diff line
@@ -4989,6 +4989,15 @@
        <attr name="startDelay" format="integer" />
        <!-- Interpolator to be used in the animations spawned by this transition. -->
        <attr name="interpolator" />
        <!-- The match order to use for the transition. This is a comma-separated
             list of values, containing one or more of the following:
             id, itemId, viewName, instance. These correspond to
             {@link android.transition.Transition#MATCH_ID},
             {@link android.transition.Transition#MATCH_ITEM_ID},
             {@link android.transition.Transition#MATCH_VIEW_NAME}, and
             {@link android.transition.Transition#MATCH_INSTANCE}, respectively.
             This corresponds to {@link android.transition.Transition#setMatchOrder(int...)}. -->
        <attr name="matchOrder" format="string" />
    </declare-styleable>

    <!-- Use <code>fade</code>as the root tag of the XML resource that
+1 −0
Original line number Diff line number Diff line
@@ -2170,6 +2170,7 @@
  <public type="attr" name="splitTrack" />
  <public type="attr" name="targetViewName" />
  <public type="attr" name="excludeViewName" />
  <public type="attr" name="matchOrder" />

  <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />