summaryrefslogtreecommitdiffstats
path: root/core/java/android/view/animation/LayoutAnimationController.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/view/animation/LayoutAnimationController.java')
-rw-r--r--core/java/android/view/animation/LayoutAnimationController.java435
1 files changed, 435 insertions, 0 deletions
diff --git a/core/java/android/view/animation/LayoutAnimationController.java b/core/java/android/view/animation/LayoutAnimationController.java
new file mode 100644
index 0000000..882e738
--- /dev/null
+++ b/core/java/android/view/animation/LayoutAnimationController.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.animation;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.Random;
+
+/**
+ * A layout animation controller is used to animated a layout's, or a view
+ * group's, children. Each child uses the same animation but for every one of
+ * them, the animation starts at a different time. A layout animation controller
+ * is used by {@link android.view.ViewGroup} to compute the delay by which each
+ * child's animation start must be offset. The delay is computed by using
+ * characteristics of each child, like its index in the view group.
+ *
+ * This standard implementation computes the delay by multiplying a fixed
+ * amount of miliseconds by the index of the child in its parent view group.
+ * Subclasses are supposed to override
+ * {@link #getDelayForView(android.view.View)} to implement a different way
+ * of computing the delay. For instance, a
+ * {@link android.view.animation.GridLayoutAnimationController} will compute the
+ * delay based on the column and row indices of the child in its parent view
+ * group.
+ *
+ * Information used to compute the animation delay of each child are stored
+ * in an instance of
+ * {@link android.view.animation.LayoutAnimationController.AnimationParameters},
+ * itself stored in the {@link android.view.ViewGroup.LayoutParams} of the view.
+ *
+ * @attr ref android.R.styleable#LayoutAnimation_delay
+ * @attr ref android.R.styleable#LayoutAnimation_animationOrder
+ * @attr ref android.R.styleable#LayoutAnimation_interpolator
+ * @attr ref android.R.styleable#LayoutAnimation_animation
+ */
+public class LayoutAnimationController {
+ /**
+ * Distributes the animation delays in the order in which view were added
+ * to their view group.
+ */
+ public static final int ORDER_NORMAL = 0;
+
+ /**
+ * Distributes the animation delays in the reverse order in which view were
+ * added to their view group.
+ */
+ public static final int ORDER_REVERSE = 1;
+
+ /**
+ * Randomly distributes the animation delays.
+ */
+ public static final int ORDER_RANDOM = 2;
+
+ /**
+ * The animation applied on each child of the view group on which this
+ * layout animation controller is set.
+ */
+ protected Animation mAnimation;
+
+ /**
+ * The randomizer used when the order is set to random. Subclasses should
+ * use this object to avoid creating their own.
+ */
+ protected Random mRandomizer;
+
+ /**
+ * The interpolator used to interpolate the delays.
+ */
+ protected Interpolator mInterpolator;
+
+ private float mDelay;
+ private int mOrder;
+
+ private long mDuration;
+ private long mMaxDelay;
+
+ /**
+ * Creates a new layout animation controller from external resources.
+ *
+ * @param context the Context the view group is running in, through which
+ * it can access the resources
+ * @param attrs the attributes of the XML tag that is inflating the
+ * layout animation controller
+ */
+ public LayoutAnimationController(Context context, AttributeSet attrs) {
+ TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.LayoutAnimation);
+
+ Animation.Description d = Animation.Description.parseValue(
+ a.peekValue(com.android.internal.R.styleable.LayoutAnimation_delay));
+ mDelay = d.value;
+
+ mOrder = a.getInt(com.android.internal.R.styleable.LayoutAnimation_animationOrder, ORDER_NORMAL);
+
+ int resource = a.getResourceId(com.android.internal.R.styleable.LayoutAnimation_animation, 0);
+ if (resource > 0) {
+ setAnimation(context, resource);
+ }
+
+ resource = a.getResourceId(com.android.internal.R.styleable.LayoutAnimation_interpolator, 0);
+ if (resource > 0) {
+ setInterpolator(context, resource);
+ }
+
+ a.recycle();
+ }
+
+ /**
+ * Creates a new layout animation controller with a delay of 50%
+ * and the specified animation.
+ *
+ * @param animation the animation to use on each child of the view group
+ */
+ public LayoutAnimationController(Animation animation) {
+ this(animation, 0.5f);
+ }
+
+ /**
+ * Creates a new layout animation controller with the specified delay
+ * and the specified animation.
+ *
+ * @param animation the animation to use on each child of the view group
+ * @param delay the delay by which each child's animation must be offset
+ */
+ public LayoutAnimationController(Animation animation, float delay) {
+ mDelay = delay;
+ setAnimation(animation);
+ }
+
+ /**
+ * Returns the order used to compute the delay of each child's animation.
+ *
+ * @return one of {@link #ORDER_NORMAL}, {@link #ORDER_REVERSE} or
+ * {@link #ORDER_RANDOM)
+ *
+ * @attr ref android.R.styleable#LayoutAnimation_animationOrder
+ */
+ public int getOrder() {
+ return mOrder;
+ }
+
+ /**
+ * Sets the order used to compute the delay of each child's animation.
+ *
+ * @param order one of {@link #ORDER_NORMAL}, {@link #ORDER_REVERSE} or
+ * {@link #ORDER_RANDOM}
+ *
+ * @attr ref android.R.styleable#LayoutAnimation_animationOrder
+ */
+ public void setOrder(int order) {
+ mOrder = order;
+ }
+
+ /**
+ * Sets the animation to be run on each child of the view group on which
+ * this layout animation controller is .
+ *
+ * @param context the context from which the animation must be inflated
+ * @param resourceID the resource identifier of the animation
+ *
+ * @see #setAnimation(Animation)
+ * @see #getAnimation()
+ *
+ * @attr ref android.R.styleable#LayoutAnimation_animation
+ */
+ public void setAnimation(Context context, int resourceID) {
+ setAnimation(AnimationUtils.loadAnimation(context, resourceID));
+ }
+
+ /**
+ * Sets the animation to be run on each child of the view group on which
+ * this layout animation controller is .
+ *
+ * @param animation the animation to run on each child of the view group
+
+ * @see #setAnimation(android.content.Context, int)
+ * @see #getAnimation()
+ *
+ * @attr ref android.R.styleable#LayoutAnimation_animation
+ */
+ public void setAnimation(Animation animation) {
+ mAnimation = animation;
+ mAnimation.setFillBefore(true);
+ }
+
+ /**
+ * Returns the animation applied to each child of the view group on which
+ * this controller is set.
+ *
+ * @return an {@link android.view.animation.Animation} instance
+ *
+ * @see #setAnimation(android.content.Context, int)
+ * @see #setAnimation(Animation)
+ */
+ public Animation getAnimation() {
+ return mAnimation;
+ }
+
+ /**
+ * Sets the interpolator used to interpolate the delays between the
+ * children.
+ *
+ * @param context the context from which the interpolator must be inflated
+ * @param resourceID the resource identifier of the interpolator
+ *
+ * @see #getInterpolator()
+ * @see #setInterpolator(Interpolator)
+ *
+ * @attr ref android.R.styleable#LayoutAnimation_interpolator
+ */
+ public void setInterpolator(Context context, int resourceID) {
+ setInterpolator(AnimationUtils.loadInterpolator(context, resourceID));
+ }
+
+ /**
+ * Sets the interpolator used to interpolate the delays between the
+ * children.
+ *
+ * @param interpolator the interpolator
+ *
+ * @see #getInterpolator()
+ * @see #setInterpolator(Interpolator)
+ *
+ * @attr ref android.R.styleable#LayoutAnimation_interpolator
+ */
+ public void setInterpolator(Interpolator interpolator) {
+ mInterpolator = interpolator;
+ }
+
+ /**
+ * Returns the interpolator used to interpolate the delays between the
+ * children.
+ *
+ * @return an {@link android.view.animation.Interpolator}
+ */
+ public Interpolator getInterpolator() {
+ return mInterpolator;
+ }
+
+ /**
+ * Returns the delay by which the children's animation are offset. The
+ * delay is expressed as a fraction of the animation duration.
+ *
+ * @return a fraction of the animation duration
+ *
+ * @see #setDelay(float)
+ */
+ public float getDelay() {
+ return mDelay;
+ }
+
+ /**
+ * Sets the delay, as a fraction of the animation duration, by which the
+ * children's animations are offset. The general formula is:
+ *
+ * <pre>
+ * child animation delay = child index * delay * animation duration
+ * </pre>
+ *
+ * @param delay a fraction of the animation duration
+ *
+ * @see #getDelay()
+ */
+ public void setDelay(float delay) {
+ mDelay = delay;
+ }
+
+ /**
+ * Indicates whether two children's animations will overlap. Animations
+ * overlap when the delay is lower than 100% (or 1.0).
+ *
+ * @return true if animations will overlap, false otherwise
+ */
+ public boolean willOverlap() {
+ return mDelay < 1.0f;
+ }
+
+ /**
+ * Starts the animation.
+ */
+ public void start() {
+ mDuration = mAnimation.getDuration();
+ mMaxDelay = Long.MIN_VALUE;
+ mAnimation.setStartTime(-1);
+ }
+
+ /**
+ * Returns the animation to be applied to the specified view. The returned
+ * animation is delayed by an offset computed according to the information
+ * provided by
+ * {@link android.view.animation.LayoutAnimationController.AnimationParameters}.
+ * This method is called by view groups to obtain the animation to set on
+ * a specific child.
+ *
+ * @param view the view to animate
+ * @return an animation delayed by the number of milliseconds returned by
+ * {@link #getDelayForView(android.view.View)}
+ *
+ * @see #getDelay()
+ * @see #setDelay(float)
+ * @see #getDelayForView(android.view.View)
+ */
+ public final Animation getAnimationForView(View view) {
+ final long delay = getDelayForView(view) + mAnimation.getStartOffset();
+ mMaxDelay = Math.max(mMaxDelay, delay);
+
+ try {
+ final Animation animation = mAnimation.clone();
+ animation.setStartOffset(delay);
+ return animation;
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Indicates whether the layout animation is over or not. A layout animation
+ * is considered done when the animation with the longest delay is done.
+ *
+ * @return true if all of the children's animations are over, false otherwise
+ */
+ public boolean isDone() {
+ return AnimationUtils.currentAnimationTimeMillis() >
+ mAnimation.getStartTime() + mMaxDelay + mDuration;
+ }
+
+ /**
+ * Returns the amount of milliseconds by which the specified view's
+ * animation must be delayed or offset. Subclasses should override this
+ * method to return a suitable value.
+ *
+ * This implementation returns <code>child animation delay</code>
+ * milliseconds where:
+ *
+ * <pre>
+ * child animation delay = child index * delay
+ * </pre>
+ *
+ * The index is retrieved from the
+ * {@link android.view.animation.LayoutAnimationController.AnimationParameters}
+ * found in the view's {@link android.view.ViewGroup.LayoutParams}.
+ *
+ * @param view the view for which to obtain the animation's delay
+ * @return a delay in milliseconds
+ *
+ * @see #getAnimationForView(android.view.View)
+ * @see #getDelay()
+ * @see #getTransformedIndex(android.view.animation.LayoutAnimationController.AnimationParameters)
+ * @see android.view.ViewGroup.LayoutParams
+ */
+ protected long getDelayForView(View view) {
+ ViewGroup.LayoutParams lp = view.getLayoutParams();
+ AnimationParameters params = lp.layoutAnimationParameters;
+
+ if (params == null) {
+ return 0;
+ }
+
+ final float delay = mDelay * mAnimation.getDuration();
+ final long viewDelay = (long) (getTransformedIndex(params) * delay);
+ final float totalDelay = delay * params.count;
+
+ if (mInterpolator == null) {
+ mInterpolator = new LinearInterpolator();
+ }
+
+ float normalizedDelay = viewDelay / totalDelay;
+ normalizedDelay = mInterpolator.getInterpolation(normalizedDelay);
+
+ return (long) (normalizedDelay * totalDelay);
+ }
+
+ /**
+ * Transforms the index stored in
+ * {@link android.view.animation.LayoutAnimationController.AnimationParameters}
+ * by the order returned by {@link #getOrder()}. Subclasses should override
+ * this method to provide additional support for other types of ordering.
+ * This method should be invoked by
+ * {@link #getDelayForView(android.view.View)} prior to any computation.
+ *
+ * @param params the animation parameters containing the index
+ * @return a transformed index
+ */
+ protected int getTransformedIndex(AnimationParameters params) {
+ switch (getOrder()) {
+ case ORDER_REVERSE:
+ return params.count - 1 - params.index;
+ case ORDER_RANDOM:
+ if (mRandomizer == null) {
+ mRandomizer = new Random();
+ }
+ return (int) (params.count * mRandomizer.nextFloat());
+ case ORDER_NORMAL:
+ default:
+ return params.index;
+ }
+ }
+
+ /**
+ * The set of parameters that has to be attached to each view contained in
+ * the view group animated by the layout animation controller. These
+ * parameters are used to compute the start time of each individual view's
+ * animation.
+ */
+ public static class AnimationParameters {
+ /**
+ * The number of children in the view group containing the view to which
+ * these parameters are attached.
+ */
+ public int count;
+
+ /**
+ * The index of the view to which these parameters are attached in its
+ * containing view group.
+ */
+ public int index;
+ }
+}