package com.marshalchen.common.uimodule.easyandroidanimations; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.graphics.Point; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateDecelerateInterpolator; import java.util.ArrayList; import java.util.List; /** * This animation translates the view within its parent view and according to * the ArrayList<Point> provided by the user. The values of X and Y in each * Point must be in the range of 0-100. Note: The status bar and action bar are * not taken into consideration for the translation. * * @author SiYao * */ public class PathAnimation extends Animation implements Combinable { public static final int ANCHOR_CENTER = 0, ANCHOR_TOP_LEFT = 1, ANCHOR_TOP_RIGHT = 2, ANCHOR_BOTTOM_LEFT = 3, ANCHOR_BOTTOM_RIGHT = 4; ArrayList<Point> points; int anchorPoint; TimeInterpolator interpolator; long duration; AnimationListener listener; /** * This animation translates the view within its parent view and according * to the ArrayList<Point> provided by the user. The values of X and Y in * each Point must be in the range of 0-100. Note: The status bar and action * bar are not taken into consideration for the translation. * * @param view * The view to be animated. */ public PathAnimation(View view) { this.view = view; points = null; anchorPoint = ANCHOR_CENTER; interpolator = new AccelerateDecelerateInterpolator(); duration = DURATION_LONG; listener = null; } @Override public void animate() { getAnimatorSet().start(); } @Override public AnimatorSet getAnimatorSet() { ViewGroup parentView = (ViewGroup) view.getParent(), rootView = (ViewGroup) view .getRootView(); while (!parentView.equals(rootView)) { parentView.setClipChildren(false); parentView = (ViewGroup) parentView.getParent(); } rootView.setClipChildren(false); AnimatorSet pathSet = new AnimatorSet(); int numOfPoints = points.size(); AnimatorSet[] pathAnimSetArray = new AnimatorSet[numOfPoints]; List<Animator> pathAnimList = new ArrayList<Animator>(); parentView = (ViewGroup) view.getParent(); int parentWidth = parentView.getWidth(), parentHeight = parentView .getHeight(), viewWidth = view.getWidth(), viewHeight = view .getHeight(); float posX, posY; for (int i = 0; i < numOfPoints; i++) { posX = (points.get(i).x / 100f * parentWidth); posY = (points.get(i).y / 100f * parentHeight); switch (anchorPoint) { case ANCHOR_CENTER: posX = posX - viewWidth / 2; posY = posY - viewHeight / 2; break; case ANCHOR_TOP_RIGHT: posX -= viewWidth; break; case ANCHOR_BOTTOM_LEFT: posY -= viewHeight; break; case ANCHOR_BOTTOM_RIGHT: posX = posX - viewWidth; posY = posY - viewHeight; break; default: break; } pathAnimSetArray[i] = new AnimatorSet(); pathAnimSetArray[i].playTogether( ObjectAnimator.ofFloat(view, View.X, posX), ObjectAnimator.ofFloat(view, View.Y, posY)); pathAnimList.add(pathAnimSetArray[i]); } pathSet.playSequentially(pathAnimList); pathSet.setInterpolator(interpolator); pathSet.setDuration(duration / numOfPoints); pathSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (getListener() != null) { getListener().onAnimationEnd(PathAnimation.this); } } }); return pathSet; } /** * @return The ArrayList<Point> for the view to translate to. * @see java.util.ArrayList */ public ArrayList<Point> getPoints() { return points; } /** * @param points * The ArrayList<Point> to set for the view to translate to. * @return This object, allowing calls to methods in this class to be * chained. * @see java.util.ArrayList */ public PathAnimation setPoints(ArrayList<Point> points) { this.points = points; return this; } /** * The available anchor points at which to translate the view are * <code>ANCHOR_CENTER</code>, <code>ANCHOR_TOP_LEFT</code>, * <code>ANCHOR_TOP_RIGHT</code>, <code>ANCHOR_BOTTOM_LEFT</code> and * <code>ANCHOR_BOTTOM_RIGHT</code>. * * @return The anchor point at which to translate the view. */ public int getAnchorPoint() { return anchorPoint; } /** * The available anchor points at which to translate the view are * <code>ANCHOR_CENTER</code>, <code>ANCHOR_TOP_LEFT</code>, * <code>ANCHOR_TOP_RIGHT</code>, <code>ANCHOR_BOTTOM_LEFT</code> and * <code>ANCHOR_BOTTOM_RIGHT</code>. * * @param anchorPoint * The anchor point to set at which to translate the view. * @return This object, allowing calls to methods in this class to be * chained. */ public PathAnimation setAnchorPoint(int anchorPoint) { this.anchorPoint = anchorPoint; return this; } /** * @return The interpolator of the entire animation. */ public TimeInterpolator getInterpolator() { return interpolator; } /** * @param interpolator * The interpolator of the entire animation to set. */ public PathAnimation setInterpolator(TimeInterpolator interpolator) { this.interpolator = interpolator; return this; } /** * @return The duration of the entire animation. */ public long getDuration() { return duration; } /** * @param duration * The duration of the entire animation to set. * @return This object, allowing calls to methods in this class to be * chained. */ public PathAnimation setDuration(long duration) { this.duration = duration; return this; } /** * @return The listener for the end of the animation. */ public AnimationListener getListener() { return listener; } /** * @param listener * The listener to set for the end of the animation. * @return This object, allowing calls to methods in this class to be * chained. */ public PathAnimation setListener(AnimationListener listener) { this.listener = listener; return this; } }