Android 控件自动“移入、暂停、移出”效果的实现

一个常见的效果:控件自动移入屏幕,停留几秒,再移出屏幕。项目中想做,但没找到合适的教程,于是自己写了一个工具类实现这个效果。本人初学android,实现方法肯定不是最优的,这只是一个没有办法的办法。构思很简单:两个动画,一个移入,一个移出,两个动画间插入一个计时器,以下是代码:
动画类(该类可以实现多个控件的同步动画,只要把所有控件传入构造方法即可,如果要执行不同的动画,各个控件单独调用就可以了,同时设置了一个开关用于控制是否执行“移出”的动作):

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,我需要他们两个同步执行动画效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值