动画类(该类可以实现多个控件的同步动画,只要把所有控件传入构造方法即可,如果要执行不同的动画,各个控件单独调用就可以了,同时设置了一个开关用于控制是否执行“移出”的动作):
package net.jackie.util; import android.annotation.SuppressLint; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.view.animation.Animation; import android.view.animation.TranslateAnimation; import android.view.animation.Animation.AnimationListener; /** * @author jackie * */ public class MoveInAndOutAnim { private static final String TAG = "MoveInAndOutAnim"; private int animDuration; private int fromXDelta; private int toXDelta; private int fromYDelta; private int toYDelt; private int keepDuration; private View[] views; private TranslateAnimation mMoveInAnim; private TranslateAnimation mMoveOutAnim; private TimerManager tm; private boolean processMoveOutAnim; /** * * @param animDuration Duration of animation * @param fromXDelta Change in X coordinate to apply at the start of the animation(generally 0) * @param toXDelta Change in X coordinate to apply at the end of the animation * (if you want to make a horizontal moving, move to right if positive value, move to left if negative value) * @param fromYDelta Change in Y coordinate to apply at the start of the animation(generally 0) * @param toYDelt Change in Y coordinate to apply at the end of the animation * (if you want to make a vertical moving, move to bottom if positive value, move to top if negative value) * @param keepDuration Duration to keep the Views displaying * @param processMoveOutAnim whether to process the move out animation * @param views Views to process the animation */ public MoveInAndOutAnim(int animDuration, int fromXDelta, int toXDelta, int fromYDelta, int toYDelt, int keepDuration, boolean processMoveOutAnim, View... views) { this.animDuration = animDuration; this.fromXDelta = fromXDelta; this.toXDelta = toXDelta; this.fromYDelta = fromYDelta; this.toYDelt = toYDelt; this.keepDuration = keepDuration; this.views = views; this.processMoveOutAnim = processMoveOutAnim; initMoveOutAnim(); initMoveInAnim(); initTimer(); } private void initMoveInAnim() { mMoveInAnim = new TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelt); mMoveInAnim.setDuration(animDuration); mMoveInAnim.setFillAfter(true); mMoveInAnim.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if (processMoveOutAnim) { tm.startTimer(); } } @Override public void onAnimationRepeat(Animation animation) { } }); } private void initMoveOutAnim() { mMoveOutAnim = new TranslateAnimation(toXDelta, fromXDelta, toYDelt, fromYDelta); mMoveOutAnim.setDuration(animDuration); mMoveOutAnim.setFillBefore(true); mMoveOutAnim.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { clearAnim(); } @Override public void onAnimationRepeat(Animation animation) { } }); } @SuppressLint("HandlerLeak") private void initTimer() { // Initial timer to control closing of 'Too Short' dialog // In fact, delay controls how long to keep the Views, so do not set it to 0 tm = new TimerManager(keepDuration, keepDuration); Handler mHandler = new Handler() { @Override public void handleMessage( Message msg) { super.handleMessage(msg); switch(msg.what) { case TimerManager.LOAD_PROGRESS : for(View view : views) { view.startAnimation(mMoveOutAnim); } tm.closeTimer(); break; case TimerManager.CLOSE_PROGRESS : // Do nothing Log.d(TAG, "Timer for 'Keep View' is closed."); break; } } }; tm.setHandler(mHandler); } public void startAnim() { for(View view : views) { view.startAnimation(mMoveInAnim); } } private void clearAnim() { for(View view : views) { view.clearAnimation(); } } }
以上动画中用到了一个计时器类TimerManager,也是一个工具类,封装了一个计时器,可以单独用于计时器实例的取得:
package net.jackie.util; import java.util.Timer; import java.util.TimerTask; import android.os.Handler; import android.os.Message; /** * Generate a timer object with specified 'delay' and 'period', * you can handle events with 'TimerManager.LOAD_PROGRESS' * and 'TimerManager.CLOSE_PROGRESS', then do your progress. * If you want to get 'timerId', just get it from 'arg1' * * @author jackie * */ public class TimerManager { private Handler mHandler; /** Timer **/ private Timer timer = null; /** TimerTask **/ private TimerTask timerTask = null; /** Delay Time in milliseconds **/ private int mDelay; /** Period in milliseconds **/ private int mPeriod; /** Timer in progressing flag **/ public static final int LOAD_PROGRESS = 0; /** Timer close flag **/ public static final int CLOSE_PROGRESS = 1; /** TimerId **/ private int mTimerId = 0; public TimerManager(int delay, int period) { this.mDelay = delay; this.mPeriod = period; } /** * * @param handler your own handler to handle the events from this timer * @param delay amount of time in milliseconds before first execution * @param period amount of time in milliseconds between subsequent executions */ public TimerManager(Handler handler, int delay, int period) { this.mHandler = handler; this.mDelay = delay; this.mPeriod = period; } public void startTimer() { if (timerTask == null) { timerTask = new TimerTask() { @Override public void run() { Message msg = new Message(); msg.what = LOAD_PROGRESS; msg.arg1 = (int) (++mTimerId); if (mHandler != null) { mHandler.sendMessage(msg); } } }; timer = new Timer(); timer.schedule(timerTask, mDelay, mPeriod); } } public void closeTimer() { if (timer != null) { timer.cancel(); timer = null; } if (timerTask != null) { timerTask = null; } mTimerId = 0; if (mHandler != null) { mHandler.sendEmptyMessage(CLOSE_PROGRESS); } } public void setHandler(Handler handler) { this.mHandler = handler; } }
用法很简单,只要构造MoveInAndOutAnim,并调用startAnim方法即可:
MoveInAndOutAnim anim = new MoveInAndOutAnim( ANIMATION_DURATION, 0, 0, 0, topBarHeight, SHOW_ADDRESS_DELAY, true, showAddressLL, mLocationIv); anim.startAnim();
showAddressLL和mLocationIv就是我自己的两个控件,一个是LinearLayout一个是ImageView,我需要他们两个同步执行动画效果。