/* * Copyright (C) 2011 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; import android.animation.Animator; import android.animation.ValueAnimator; import android.animation.TimeInterpolator; import java.util.ArrayList; import java.util.HashMap; import java.util.Set; /** * This class enables automatic and optimized animation of select properties on View objects. * If only one or two properties on a View object are being animated, then using an * {@link android.animation.ObjectAnimator} is fine; the property setters called by ObjectAnimator * are well equipped to do the right thing to set the property and invalidate the view * appropriately. But if several properties are animated simultaneously, or if you just want a * more convenient syntax to animate a specific property, then ViewPropertyAnimator might be * more well-suited to the task. * *
This class may provide better performance for several simultaneous animations, because * it will optimize invalidate calls to take place only once for several properties instead of each * animated property independently causing its own invalidation. Also, the syntax of using this * class could be easier to use because the caller need only tell the View object which * property to animate, and the value to animate either to or by, and this class handles the * details of configuring the underlying Animator class and starting it.
* *This class is not constructed by the caller, but rather by the View whose properties * it will animate. Calls to {@link android.view.View#animate()} will return a reference * to the appropriate ViewPropertyAnimator object for that View.
* */ public class ViewPropertyAnimator { /** * The View whose properties are being animated by this class. This is set at * construction time. */ private final View mView; /** * The duration of the underlying Animator object. By default, we don't set the duration * on the Animator and just use its default duration. If the duration is ever set on this * Animator, then we use the duration that it was set to. */ private long mDuration; /** * A flag indicating whether the duration has been set on this object. If not, we don't set * the duration on the underlying Animator, but instead just use its default duration. */ private boolean mDurationSet = false; /** * The startDelay of the underlying Animator object. By default, we don't set the startDelay * on the Animator and just use its default startDelay. If the startDelay is ever set on this * Animator, then we use the startDelay that it was set to. */ private long mStartDelay = 0; /** * A flag indicating whether the startDelay has been set on this object. If not, we don't set * the startDelay on the underlying Animator, but instead just use its default startDelay. */ private boolean mStartDelaySet = false; /** * The interpolator of the underlying Animator object. By default, we don't set the interpolator * on the Animator and just use its default interpolator. If the interpolator is ever set on * this Animator, then we use the interpolator that it was set to. */ private TimeInterpolator mInterpolator; /** * A flag indicating whether the interpolator has been set on this object. If not, we don't set * the interpolator on the underlying Animator, but instead just use its default interpolator. */ private boolean mInterpolatorSet = false; /** * Listener for the lifecycle events of the underlying */ private Animator.AnimatorListener mListener = null; /** * This listener is the mechanism by which the underlying Animator causes changes to the * properties currently being animated, as well as the cleanup after an animation is * complete. */ private AnimatorEventListener mAnimatorEventListener = new AnimatorEventListener(); /** * This list holds the properties that have been asked to animate. We allow the caller to * request several animations prior to actually starting the underlying animator. This * enables us to run one single animator to handle several properties in parallel. Each * property is tossed onto the pending list until the animation actually starts (which is * done by posting it onto mView), at which time the pending list is cleared and the properties * on that list are added to the list of properties associated with that animator. */ ArrayListstart()
* is optional because all animations start automatically at the next opportunity. However,
* if the animations are needed to start immediately and synchronously (not at the time when
* the next event is processed by the hierarchy, which is when the animations would begin
* otherwise), then this method can be used.
*/
public void start() {
startAnimation();
}
/**
* Cancels all property animations that are currently running or pending.
*/
public void cancel() {
if (mAnimatorMap.size() > 0) {
HashMapx
property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setX(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator x(float value) {
animateProperty(X, value);
return this;
}
/**
* This method will cause the View's x
property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setX(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator xBy(float value) {
animatePropertyBy(X, value);
return this;
}
/**
* This method will cause the View's y
property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setY(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator y(float value) {
animateProperty(Y, value);
return this;
}
/**
* This method will cause the View's y
property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setY(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator yBy(float value) {
animatePropertyBy(Y, value);
return this;
}
/**
* This method will cause the View's rotation
property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setRotation(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator rotation(float value) {
animateProperty(ROTATION, value);
return this;
}
/**
* This method will cause the View's rotation
property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setRotation(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator rotationBy(float value) {
animatePropertyBy(ROTATION, value);
return this;
}
/**
* This method will cause the View's rotationX
property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setRotationX(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator rotationX(float value) {
animateProperty(ROTATION_X, value);
return this;
}
/**
* This method will cause the View's rotationX
property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setRotationX(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator rotationXBy(float value) {
animatePropertyBy(ROTATION_X, value);
return this;
}
/**
* This method will cause the View's rotationY
property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setRotationY(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator rotationY(float value) {
animateProperty(ROTATION_Y, value);
return this;
}
/**
* This method will cause the View's rotationY
property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setRotationY(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator rotationYBy(float value) {
animatePropertyBy(ROTATION_Y, value);
return this;
}
/**
* This method will cause the View's translationX
property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setTranslationX(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator translationX(float value) {
animateProperty(TRANSLATION_X, value);
return this;
}
/**
* This method will cause the View's translationX
property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setTranslationX(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator translationXBy(float value) {
animatePropertyBy(TRANSLATION_X, value);
return this;
}
/**
* This method will cause the View's translationY
property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setTranslationY(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator translationY(float value) {
animateProperty(TRANSLATION_Y, value);
return this;
}
/**
* This method will cause the View's translationY
property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setTranslationY(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator translationYBy(float value) {
animatePropertyBy(TRANSLATION_Y, value);
return this;
}
/**
* This method will cause the View's scaleX
property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setScaleX(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator scaleX(float value) {
animateProperty(SCALE_X, value);
return this;
}
/**
* This method will cause the View's scaleX
property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setScaleX(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator scaleXBy(float value) {
animatePropertyBy(SCALE_X, value);
return this;
}
/**
* This method will cause the View's scaleY
property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setScaleY(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator scaleY(float value) {
animateProperty(SCALE_Y, value);
return this;
}
/**
* This method will cause the View's scaleY
property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setScaleY(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator scaleYBy(float value) {
animatePropertyBy(SCALE_Y, value);
return this;
}
/**
* This method will cause the View's alpha
property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setAlpha(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator alpha(float value) {
animateProperty(ALPHA, value);
return this;
}
/**
* This method will cause the View's alpha
property to be animated by the
* specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setAlpha(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator alphaBy(float value) {
animatePropertyBy(ALPHA, value);
return this;
}
/**
* Starts the underlying Animator for a set of properties. We use a single animator that
* simply runs from 0 to 1, and then use that fractional value to set each property
* value accordingly.
*/
private void startAnimation() {
ValueAnimator animator = ValueAnimator.ofFloat(1.0f);
ArrayList