438 lines
15 KiB
Java
438 lines
15 KiB
Java
/*
|
|
* 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.annotation.AnimRes;
|
|
import android.annotation.InterpolatorRes;
|
|
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 animate the children of a layout or a view
|
|
* group. 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), context);
|
|
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, @AnimRes 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, @InterpolatorRes 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;
|
|
}
|
|
}
|