All Downloads are FREE. Search and download functionalities are using the official Maven repository.

android.view.animation.LayoutAnimationController Maven / Gradle / Ivy

Go to download

A library jar that provides APIs for Applications written for the Google Android Platform.

There is a newer version: 14-robolectric-10818077
Show newest version
/*
 * 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:
     *
     * 
     * child animation delay = child index * delay * animation duration
     * 
* * @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 child animation delay * milliseconds where: * *
     * child animation delay = child index * delay
     * 
* * 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; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy