Merge "Allow changing order of matching Views in Transitions."
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
Reference in New Issue
Block a user