コード例 #1
0
 /**
  * This method sorts the current set of nodes, if needed. The sort is a simple DependencyGraph
  * sort, which goes like this: - All nodes without dependencies become 'roots' - while roots list
  * is not null - for each root r - add r to sorted list - remove r as a dependency from any other
  * node - any nodes with no dependencies are added to the roots list
  */
 private void sortNodes() {
   if (mNeedsSort) {
     mSortedNodes.clear();
     ArrayList<Node> roots = new ArrayList<Node>();
     int numNodes = mNodes.size();
     for (int i = 0; i < numNodes; ++i) {
       Node node = mNodes.get(i);
       if (node.dependencies == null || node.dependencies.size() == 0) {
         roots.add(node);
       }
     }
     ArrayList<Node> tmpRoots = new ArrayList<Node>();
     while (roots.size() > 0) {
       int numRoots = roots.size();
       for (int i = 0; i < numRoots; ++i) {
         Node root = roots.get(i);
         mSortedNodes.add(root);
         if (root.nodeDependents != null) {
           int numDependents = root.nodeDependents.size();
           for (int j = 0; j < numDependents; ++j) {
             Node node = root.nodeDependents.get(j);
             node.nodeDependencies.remove(root);
             if (node.nodeDependencies.size() == 0) {
               tmpRoots.add(node);
             }
           }
         }
       }
       roots.clear();
       roots.addAll(tmpRoots);
       tmpRoots.clear();
     }
     mNeedsSort = false;
     if (mSortedNodes.size() != mNodes.size()) {
       throw new IllegalStateException("Circular dependencies cannot exist" + " in AnimatorSet");
     }
   } else {
     // Doesn't need sorting, but still need to add in the nodeDependencies list
     // because these get removed as the event listeners fire and the dependencies
     // are satisfied
     int numNodes = mNodes.size();
     for (int i = 0; i < numNodes; ++i) {
       Node node = mNodes.get(i);
       if (node.dependencies != null && node.dependencies.size() > 0) {
         int numDependencies = node.dependencies.size();
         for (int j = 0; j < numDependencies; ++j) {
           Dependency dependency = node.dependencies.get(j);
           if (node.nodeDependencies == null) {
             node.nodeDependencies = new ArrayList<Node>();
           }
           if (!node.nodeDependencies.contains(dependency.node)) {
             node.nodeDependencies.add(dependency.node);
           }
         }
       }
       // nodes are 'done' by default; they become un-done when started, and done
       // again when ended
       node.done = false;
     }
   }
 }
コード例 #2
0
  @Override
  public AnimatorSet clone() {
    final AnimatorSet anim = (AnimatorSet) super.clone();
    /*
     * The basic clone() operation copies all items. This doesn't work very well for
     * AnimatorSet, 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.mTerminated = false;
    anim.mStarted = false;
    anim.mPlayingSet = new ArrayList<Animator>();
    anim.mNodeMap = new HashMap<Animator, 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 AnimatorSet.
    // 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 AnimatorSet; these will
      // be set up when the clone's nodes are sorted
      ArrayList<AnimatorListener> cloneListeners = nodeClone.animation.getListeners();
      if (cloneListeners != null) {
        ArrayList<AnimatorListener> listenersToRemove = null;
        for (AnimatorListener listener : cloneListeners) {
          if (listener instanceof AnimatorSetListener) {
            if (listenersToRemove == null) {
              listenersToRemove = new ArrayList<AnimatorListener>();
            }
            listenersToRemove.add(listener);
          }
        }
        if (listenersToRemove != null) {
          for (AnimatorListener 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;
  }