Add facilities for layout transitions

Change-Id: I5c73ce6c6ba3bc9e3b57fcfbbcab37d511db6132
This commit is contained in:
Chet Haase
2010-08-23 11:39:53 -07:00
parent 63134b3aee
commit 49afa5bc10
9 changed files with 200 additions and 43 deletions

View File

@@ -19779,6 +19779,8 @@
deprecated="not deprecated"
visibility="public"
>
<implements name="java.lang.Cloneable">
</implements>
<constructor name="Animatable"
type="android.animation.Animatable"
static="false"
@@ -19811,6 +19813,19 @@
visibility="public"
>
</method>
<method name="clone"
return="android.animation.Animatable"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<exception name="CloneNotSupportedException" type="java.lang.CloneNotSupportedException">
</exception>
</method>
<method name="end"
return="void"
abstract="false"
@@ -269619,7 +269634,7 @@
>
<parameter name="numBits" type="int">
</parameter>
<parameter name="rnd" type="java.util.Random">
<parameter name="random" type="java.util.Random">
</parameter>
</constructor>
<constructor name="BigInteger"
@@ -269633,7 +269648,7 @@
</parameter>
<parameter name="certainty" type="int">
</parameter>
<parameter name="rnd" type="java.util.Random">
<parameter name="unused" type="java.util.Random">
</parameter>
</constructor>
<constructor name="BigInteger"
@@ -269643,7 +269658,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="java.lang.String">
<parameter name="value" type="java.lang.String">
</parameter>
</constructor>
<constructor name="BigInteger"
@@ -269653,7 +269668,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="java.lang.String">
<parameter name="value" type="java.lang.String">
</parameter>
<parameter name="radix" type="int">
</parameter>
@@ -269677,7 +269692,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="byte[]">
<parameter name="value" type="byte[]">
</parameter>
</constructor>
<method name="abs"
@@ -269701,7 +269716,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="java.math.BigInteger">
<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="and"
@@ -269714,7 +269729,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="java.math.BigInteger">
<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="andNot"
@@ -269727,7 +269742,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="java.math.BigInteger">
<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="bitCount"
@@ -269775,7 +269790,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="java.math.BigInteger">
<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="divide"
@@ -269849,7 +269864,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="java.math.BigInteger">
<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="getLowestSetBit"
@@ -269908,7 +269923,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="java.math.BigInteger">
<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="min"
@@ -269921,7 +269936,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="java.math.BigInteger">
<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="mod"
@@ -269975,7 +269990,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="java.math.BigInteger">
<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="negate"
@@ -270021,7 +270036,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="java.math.BigInteger">
<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="pow"
@@ -270049,7 +270064,7 @@
>
<parameter name="bitLength" type="int">
</parameter>
<parameter name="rnd" type="java.util.Random">
<parameter name="unused" type="java.util.Random">
</parameter>
</method>
<method name="remainder"
@@ -270125,7 +270140,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="java.math.BigInteger">
<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="testBit"
@@ -270175,7 +270190,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="long">
<parameter name="value" type="long">
</parameter>
</method>
<method name="xor"
@@ -270188,7 +270203,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="val" type="java.math.BigInteger">
<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<field name="ONE"

View File

@@ -22,7 +22,7 @@ import java.util.ArrayList;
* This is the superclass for classes which provide basic support for animations which can be
* started, ended, and have <code>AnimatableListeners</code> added to them.
*/
public abstract class Animatable {
public abstract class Animatable implements Cloneable {
/**
@@ -107,6 +107,20 @@ public abstract class Animatable {
}
}
@Override
public Animatable clone() throws CloneNotSupportedException {
final Animatable anim = (Animatable) super.clone();
if (mListeners != null) {
ArrayList<AnimatableListener> oldListeners = mListeners;
anim.mListeners = new ArrayList<AnimatableListener>();
int numListeners = oldListeners.size();
for (int i = 0; i < numListeners; ++i) {
anim.mListeners.add(oldListeners.get(i));
}
}
return anim;
}
/**
* <p>An animation listener receives notifications from an animation.
* Notifications indicate animation related events, such as the end or the

View File

@@ -80,9 +80,11 @@ public class Animator<T> extends Animatable {
/**
* Internal variables
* NOTE: This object implements the clone() method, making a deep copy of any referenced
* objects. As other non-trivial fields are added to this class, make sure to add logic
* to clone() to make deep copies of them.
*/
// The first time that the animation's animateFrame() method is called. This time is used to
// determine elapsed time (and therefore the elapsed fraction) in subsequent calls
// to animateFrame()
@@ -402,7 +404,7 @@ public class Animator<T> extends Animatable {
* @return The current position in time of the animation.
*/
public long getCurrentPlayTime() {
if (!mInitialized) {
if (!mInitialized || mPlayingState == STOPPED) {
return 0;
}
return AnimationUtils.currentAnimationTimeMillis() - mStartTime;
@@ -954,6 +956,39 @@ public class Animator<T> extends Animatable {
}
}
@Override
public Animator clone() throws CloneNotSupportedException {
final Animator anim = (Animator) super.clone();
if (mUpdateListeners != null) {
ArrayList<AnimatorUpdateListener> oldListeners = mUpdateListeners;
anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
int numListeners = oldListeners.size();
for (int i = 0; i < numListeners; ++i) {
anim.mUpdateListeners.add(oldListeners.get(i));
}
}
anim.mSeekTime = -1;
anim.mPlayingBackwards = false;
anim.mCurrentIteration = 0;
anim.mInitialized = false;
anim.mPlayingState = STOPPED;
anim.mStartedDelay = false;
PropertyValuesHolder[] oldValues = mValues;
if (oldValues != null) {
int numValues = oldValues.length;
anim.mValues = new PropertyValuesHolder[numValues];
for (int i = 0; i < numValues; ++i) {
anim.mValues[i] = oldValues[i];
}
anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
for (int i = 0; i < numValues; ++i) {
PropertyValuesHolder valuesHolder = mValues[i];
anim.mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
}
}
return anim;
}
/**
* Implementors of this interface can add themselves as update listeners
* to an <code>Animator</code> instance to receive callbacks on every animation

View File

@@ -228,4 +228,10 @@ public final class PropertyAnimator<T> extends Animator<T> {
mValues[i].setAnimatedValue(mTarget);
}
}
@Override
public PropertyAnimator clone() throws CloneNotSupportedException {
final PropertyAnimator anim = (PropertyAnimator) super.clone();
return anim;
}
}

View File

@@ -45,11 +45,18 @@ import java.util.HashMap;
*/
public final class Sequencer extends Animatable {
/**
* Internal variables
* NOTE: This object implements the clone() method, making a deep copy of any referenced
* objects. As other non-trivial fields are added to this class, make sure to add logic
* to clone() to make deep copies of them.
*/
/**
* Tracks animations currently being played, so that we know what to
* cancel or end when cancel() or end() is called on this Sequencer
*/
private final ArrayList<Animatable> mPlayingSet = new ArrayList<Animatable>();
private ArrayList<Animatable> mPlayingSet = new ArrayList<Animatable>();
/**
* Contains all nodes, mapped to their respective Animatables. When new
@@ -57,21 +64,21 @@ public final class Sequencer extends Animatable {
* to a single node representing that Animatable, not create a new Node
* if one already exists.
*/
private final HashMap<Animatable, Node> mNodeMap = new HashMap<Animatable, Node>();
private HashMap<Animatable, Node> mNodeMap = new HashMap<Animatable, Node>();
/**
* Set of all nodes created for this Sequencer. This list is used upon
* starting the sequencer, and the nodes are placed in sorted order into the
* sortedNodes collection.
*/
private final ArrayList<Node> mNodes = new ArrayList<Node>();
private ArrayList<Node> mNodes = new ArrayList<Node>();
/**
* The sorted list of nodes. This is the order in which the animations will
* be played. The details about when exactly they will be played depend
* on the dependency relationships of the nodes.
*/
private final ArrayList<Node> mSortedNodes = new ArrayList<Node>();
private ArrayList<Node> mSortedNodes = new ArrayList<Node>();
/**
* Flag indicating whether the nodes should be sorted prior to playing. This
@@ -283,6 +290,75 @@ public final class Sequencer extends Animatable {
}
}
@Override
public Sequencer clone() throws CloneNotSupportedException {
final Sequencer anim = (Sequencer) super.clone();
/*
* The basic clone() operation copies all items. This doesn't work very well for
* Sequencer, because it will copy references that need to be recreated and state
* that may not apply. What we need to do now is put the clone in an uninitialized
* state, with fresh, empty data structures. Then we will build up the nodes list
* manually, as we clone each Node (and its animation). The clone will then be sorted,
* and will populate any appropriate lists, when it is started.
*/
anim.mNeedsSort = true;
anim.mCanceled = false;
anim.mPlayingSet = new ArrayList<Animatable>();
anim.mNodeMap = new HashMap<Animatable, Node>();
anim.mNodes = new ArrayList<Node>();
anim.mSortedNodes = new ArrayList<Node>();
// Walk through the old nodes list, cloning each node and adding it to the new nodemap.
// One problem is that the old node dependencies point to nodes in the old sequencer.
// We need to track the old/new nodes in order to reconstruct the dependencies in the clone.
HashMap<Node, Node> nodeCloneMap = new HashMap<Node, Node>(); // <old, new>
for (Node node : mNodes) {
Node nodeClone = node.clone();
nodeCloneMap.put(node, nodeClone);
anim.mNodes.add(nodeClone);
anim.mNodeMap.put(nodeClone.animation, nodeClone);
// Clear out the dependencies in the clone; we'll set these up manually later
nodeClone.dependencies = null;
nodeClone.tmpDependencies = null;
nodeClone.nodeDependents = null;
nodeClone.nodeDependencies = null;
// clear out any listeners that were set up by the sequencer; these will
// be set up when the clone's nodes are sorted
ArrayList<AnimatableListener> cloneListeners = nodeClone.animation.getListeners();
if (cloneListeners != null) {
ArrayList<AnimatableListener> listenersToRemove = null;
for (AnimatableListener listener : cloneListeners) {
if (listener instanceof SequencerAnimatableListener) {
if (listenersToRemove == null) {
listenersToRemove = new ArrayList<AnimatableListener>();
}
listenersToRemove.add(listener);
}
}
if (listenersToRemove != null) {
for (AnimatableListener listener : listenersToRemove) {
cloneListeners.remove(listener);
}
}
}
}
// Now that we've cloned all of the nodes, we're ready to walk through their
// dependencies, mapping the old dependencies to the new nodes
for (Node node : mNodes) {
Node nodeClone = nodeCloneMap.get(node);
if (node.dependencies != null) {
for (Dependency dependency : node.dependencies) {
Node clonedDependencyNode = nodeCloneMap.get(dependency.node);
Dependency cloneDependency = new Dependency(clonedDependencyNode,
dependency.rule);
nodeClone.addDependency(cloneDependency);
}
}
}
return anim;
}
/**
* This class is the mechanism by which animations are started based on events in other
* animations. If an animation has multiple dependencies on other animations, then
@@ -514,7 +590,7 @@ public final class Sequencer extends Animatable {
* both dependencies upon other nodes (in the dependencies list) as
* well as dependencies of other nodes upon this (in the nodeDependents list).
*/
private static class Node {
private static class Node implements Cloneable {
public Animatable animation;
/**
@@ -587,6 +663,13 @@ public final class Sequencer extends Animatable {
}
dependencyNode.nodeDependents.add(this);
}
@Override
public Node clone() throws CloneNotSupportedException {
Node node = (Node) super.clone();
node.animation = (Animatable) animation.clone();
return node;
}
}
/**

View File

@@ -330,7 +330,7 @@ public class Dialog implements DialogInterface, Window.Callback,
}
/**
* Similar to {@link Activity#onCreate}, you should initialized your dialog
* Similar to {@link Activity#onCreate}, you should initialize your dialog
* in this method, including calling {@link #setContentView}.
* @param savedInstanceState If this dialog is being reinitalized after a
* the hosting activity was previously shut down, holds the result from

View File

@@ -24,22 +24,26 @@ import android.os.SystemClock;
* A utility class to help log timings splits throughout a method call.
* Typical usage is:
*
* TimingLogger timings = new TimingLogger(TAG, "methodA");
* ... do some work A ...
* timings.addSplit("work A");
* ... do some work B ...
* timings.addSplit("work B");
* ... do some work C ...
* timings.addSplit("work C");
* timings.dumpToLog();
* <pre>
* TimingLogger timings = new TimingLogger(TAG, "methodA");
* // ... do some work A ...
* timings.addSplit("work A");
* // ... do some work B ...
* timings.addSplit("work B");
* // ... do some work C ...
* timings.addSplit("work C");
* timings.dumpToLog();
* </pre>
*
* The dumpToLog call would add the following to the log:
* <p>The dumpToLog call would add the following to the log:</p>
*
* D/TAG ( 3459): methodA: begin
* D/TAG ( 3459): methodA: 9 ms, work A
* D/TAG ( 3459): methodA: 1 ms, work B
* D/TAG ( 3459): methodA: 6 ms, work C
* D/TAG ( 3459): methodA: end, 16 ms
* <pre>
* D/TAG ( 3459): methodA: begin
* D/TAG ( 3459): methodA: 9 ms, work A
* D/TAG ( 3459): methodA: 1 ms, work B
* D/TAG ( 3459): methodA: 6 ms, work C
* D/TAG ( 3459): methodA: end, 16 ms
* </pre>
*/
public class TimingLogger {

View File

@@ -3438,7 +3438,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
* Sets the pressed that for this view.
* Sets the pressed state for this view.
*
* @see #isClickable()
* @see #setClickable(boolean)

View File

@@ -307,7 +307,7 @@ public abstract class Animation implements Cloneable {
* animated as well as the objects parents. (This is to support animation
* sizes being specifed relative to these dimensions.)
*
* <p>Objects that interpret a Animations should call this method when
* <p>Objects that interpret Animations should call this method when
* the sizes of the object being animated and its parent are known, and
* before calling {@link #getTransformation}.
*