Android動畫工具類的封裝實戰(zhàn)記錄
起因
最近在做一個組件化框架的封裝,現(xiàn)在開發(fā)到一些常用工具類的封裝了,突然意識到好像還沒有做動畫的工具類,于是開始著手開發(fā)之。
思路
既然要做動畫,肯定是要做屬性動畫的工具類的封裝了,由于補間動畫和逐幀動畫并不能改變目標動畫主題的實際屬性,在Android的開發(fā)中已經(jīng)越來越少人去用這兩個動畫框架做開發(fā)了,而屬性動畫則相對的越來越廣泛的使用在開發(fā)過程中了,于是這次的工具類的封裝,只針對屬性動畫來封裝。
屬性動畫對應的類叫做ObjectAnimator,主要就是用這個類來實現(xiàn)動畫的一些基礎設置,其具體的使用方式我就不寫了,有興趣的朋友可以自行學習屬性動畫的相關知識。
封裝屬性動畫工具類不可避免的還要考慮到屬性動畫的組合播放動畫的需求,而屬性動畫的組合播放有大約三種方式:
1.使用AnimatorSet的Builder來組合播放
AnimatorSet.Builder是一個使用的動畫工具類,用于方便向AnimatorSet添加動畫以及設置各種動畫之間的關系。在 AnimatorSet.Builder中,共聲明了after(long)、after(Animator)、before(Animator)、with(Animator)等四個方法。
- after(delay) 設置動畫延遲delay時間后播放
- after(anim) 設置在anim動畫結束后播放此動畫
- before(anim) 設置此動畫早于anim播放
- with(anim) 設置此動畫與anim一起播放
然后再調(diào)用paly(anim)方法來鏈式調(diào)用動畫
AnimatorSet set=new AnimatorSet(); set.play(anim1).before(anim2).with(anim3).after(anim4);
我們注意到他是先執(zhí)行的after,然后是play和with同時執(zhí)行,最后執(zhí)行的before。所以大家記住這個順序,無論怎么寫,都是這個執(zhí)行順序。
2.使用AnimatorSet的playSequentially
API
- playSequentially(List items):添加一組動畫,播放順序為逐一播放
- playSequentially(Animator… items):添加一組動畫,播放順序為逐一播放
AnimatorSet bouncer = new AnimatorSet(); ObjectAnimator objectAnimatorA = ObjectAnimator.ofFloat(btnProperty, PropertyConstant.PROPERTY_TRANSLATION_X, 0f, 300f); ObjectAnimator objectAnimatorB = ObjectAnimator.ofFloat(btnProperty, PropertyConstant.PROPERTY_TRANSLATION_Y, 0f, 300f); ObjectAnimator objectAnimatorC = ObjectAnimator.ofFloat(btnProperty, PropertyConstant.PROPERTY_ROTATION, 0f, 360f); bouncer.playSequentially(objectAnimatorA, objectAnimatorB, objectAnimatorC); bouncer.setDuration(6000); bouncer.start();
3.使用AnimatorSet的palyTogether
API
- playTogether(Collection items):添加一組動畫,播放順序為一起播放
- playTogether(Animator… items):添加一組動畫,播放順序為一起播放
AnimatorSet bouncer = new AnimatorSet(); ObjectAnimator objectAnimatorA = ObjectAnimator.ofFloat(btnProperty, PropertyConstant.PROPERTY_TRANSLATION_X, 0f, 300f); ObjectAnimator objectAnimatorB = ObjectAnimator.ofFloat(btnProperty, PropertyConstant.PROPERTY_TRANSLATION_Y, 0f, 300f); ObjectAnimator objectAnimatorC = ObjectAnimator.ofFloat(btnProperty, PropertyConstant.PROPERTY_ROTATION, 0f, 360f); bouncer.playSequentially(objectAnimatorA, objectAnimatorB, objectAnimatorC); bouncer.setDuration(6000); bouncer.start();
掌握以上的知識點后,我的思路是,其實最后就是對執(zhí)行方式的封裝,所謂的執(zhí)行方式就是如何正常的調(diào)用play,playSequentially和playTogether三個方法,這里需要合理的封裝。
還有就是對于監(jiān)聽接口的封裝,每個ObjectAnimator都有三個接口:
Animator.AnimatorListener 對整個動畫生命周期的監(jiān)聽
anim.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
Toast.makeText(MainActivity.this, "start", Toast.LENGTH_LONG).show();
}
@Override
public void onAnimationEnd(Animator animator) {
Toast.makeText(MainActivity.this, "End", Toast.LENGTH_LONG).show();
}
@Override
public void onAnimationCancel(Animator animator) {
Toast.makeText(MainActivity.this, "Cancel", Toast.LENGTH_LONG).show();
}
@Override
public void onAnimationRepeat(Animator animator) {
Toast.makeText(MainActivity.this, "rapeat", Toast.LENGTH_LONG).show();
}
});
anim.start();
ValueAnimator.AnimatorUpdateListener 對于該動畫逐幀的監(jiān)聽
ValueAnimator vanim = ValueAnimator.ofInt(0,10,20);
vanim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
//如果之前的ValueAnimtor指定的是Int的i話,那么返回的Value就是int類型,
也就是返回值類型與你創(chuàng)建的類型一致
int value = (int) valueAnimator.getAnimatedValue();
}
});
Animator.AnimatorPauseListener 對于該動畫的暫停和播放的監(jiān)聽
new Animator.AnimatorPauseListener() {
@Override
public void onAnimationPause(Animator animator) {
}
@Override
public void onAnimationResume(Animator animator) {
}
}
由于我的初步構想是使用建造者模式的鏈式調(diào)用模式來設計我的工具類,如果按照普通的寫法,那么整個監(jiān)聽接口的設置將會是災難性的,因為所有的監(jiān)聽接口的設置都是混亂的,所以這里必須處理,我的思路是,學習SpringSecurity的鏈式調(diào)用設計,為每個類型的監(jiān)聽設置自己的類,然后再讓工具主類調(diào)用該類型的監(jiān)聽接口,然后設置完畢后,在通過該監(jiān)聽接口類的and()方法回到工具類的主類型來,這樣在鏈式調(diào)用的時候就有一個起止順序,不會混亂執(zhí)行了,而且如果不用設置監(jiān)聽,不調(diào)用監(jiān)聽類設置也不會影響主類的執(zhí)行。
截取關鍵代碼,以Play方法的監(jiān)聽接口設置為例:
/**
*工具類的主類
**/
public static class AnimatorSetWrap{
PlayAnimationListener playListener;
public PlayAnimationListener toAddPlayListener(){
playListener=new PlayAnimationListener(this);
return playListener;
}
}
/**
* Play方法對應的ObjectAnimator的監(jiān)聽實例
*/
public static class PlayAnimationListener implements IAnimatorListener<PlayAnimationListener>{
private Animator.AnimatorListener animatorListener;
private ValueAnimator.AnimatorUpdateListener updateListener;
private Animator.AnimatorPauseListener pauseListener;
public AnimatorSetWrap animatorSetWrap;
public PlayAnimationListener(AnimatorSetWrap animatorSetWrap){
this.animatorSetWrap=animatorSetWrap;
}
@Override
public PlayAnimationListener setAnimatorListener(Animator.AnimatorListener animatorListener) {
this.animatorListener=animatorListener;
return this;
}
@Override
public PlayAnimationListener setUpdateListener(ValueAnimator.AnimatorUpdateListener animatorListener) {
this.updateListener=animatorListener;
return this;
}
@Override
public PlayAnimationListener setPauseListener(Animator.AnimatorPauseListener animatorListener) {
this.pauseListener=animatorListener;
return this;
}
@Override
public AnimatorSetWrap and(){
return animatorSetWrap;
}
}
/**
* 動畫監(jiān)聽的公用模板接口
* @param <T>
*/
interface IAnimatorListener<T>{
/**
* 設置AnimatorListener的方法
* @param listener
* @return
*/
T setAnimatorListener(Animator.AnimatorListener listener);
/**
* 設置AnimatorUpdateListener的方法
* @param listener
* @return
*/
T setUpdateListener(ValueAnimator.AnimatorUpdateListener listener);
/**
* 設置AnimatorPauseListener的方法
* @param listener
* @return
*/
T setPauseListener(Animator.AnimatorPauseListener listener);
/**
* 橋接動畫監(jiān)聽與動畫工具類的方法
* @return
*/
AnimatorSetWrap and();
}
具體的使用方法:
AnimatorUtil.AnimatorSetWrap animatorSetWrapDemo=new AnimatorSetWrap().toAddPlayListener().setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
LogUtils.e("數(shù)值:"+valueAnimator.getAnimatedValue());
}
}).and();
通過這種鏈式調(diào)用,只要調(diào)用到and()方法就又回到了AnimatorSetWrap工具類的實例,剩下就可以繼續(xù)調(diào)用其他動畫的方法并播放動畫了。
代碼
說了這么多,就把我的工具類代碼分享給大家吧,可能還不完善,有什么問題大家一起探討:
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import android.view.View;
import android.view.animation.LinearInterpolator;
import java.util.ArrayList;
import java.util.List;
/**
* 動畫工具類
*@package com.dhcc.commonutils
*@author jasoncool
*@createDate 2018/11/20 16:16
*@description
**/
public class AnimatorUtils {
public static final String ALPHA="Alpha";
public static final String TRANSX="TranslationX";
public static final String TRANSY="TranslationY";
public static final String SCALEX="ScaleX";
public static final String SCALEY="ScaleY";
public static final String ROTATION="Rotation";
public static final String ROTATIONX="RotationX";
public static final String ROTATIONY="RotationY";
/**
* 默認的TimeInterpolator,前后減速,中間加速
*/
private static final TimeInterpolator sDefaultInterpolator =
new LinearInterpolator();
public static AnimatorSetWrap createAnimator() {
return new AnimatorSetWrap();
}
/**
* @param interpolator 默認的TimeInterpolator
* @return
*/
public static AnimatorSetWrap createAnimator(TimeInterpolator interpolator) {
return new AnimatorSetWrap(interpolator);
}
/**
* 屬性動畫組合
* 屬性動畫組合對應的是AnimatorSet類,我們只需要new他就好。
*
* 它對應的主要有這四個方法,play,before,with,after。
* 這四個方法里面全都是填入往后兒們的animator類,
* 但是先后執(zhí)行順序不一樣,分別對應著開啟,最后,同步,最開始執(zhí)行。
* 我們注意到他是先執(zhí)行的after,然后是play和with同時執(zhí)行,最后執(zhí)行的before。
* 所以大家記住這個順序,無論怎么寫,都是這個執(zhí)行順序。
*
*/
public static class AnimatorSetWrap{
private View mView;
/**
* 不設置默認插值器時,工具類自帶的默認插值器
*/
private TimeInterpolator mTimeInterpolator;
/**
* 判斷play方法只允許執(zhí)行一次的布爾值
*/
boolean mIsPlaying=false;
/**
* 聯(lián)合動畫的動畫容器
*/
private AnimatorSet mAnimatorSet;
/**
* 聯(lián)合動畫的動畫構造器
*/
private AnimatorSet.Builder mAnimatorBuilder;
/**
* 默認執(zhí)行時間
*/
private int mDuration=1000;
/**
* play的監(jiān)聽器類
*/
PlayAnimationListener playListener;
/**
* before的監(jiān)聽器類
*/
BeforeAnimationListener beforeListener;
/**
* with的監(jiān)聽器類
*/
WithAnimationListener withListener;
/**
* after的監(jiān)聽器類
*/
AfterAnimationListener afterListener;
/**
* then的監(jiān)聽器類
*/
ThenAnimationListener thenListener;
/**
* 順序播放或者同時播放時存儲動畫的列表容器
*/
List<Animator> mAnimatorList;
/**
* 是否已經(jīng)初始化then動畫
*/
boolean mHasInitThenAnim=false;
private AnimatorSetWrap(){
this(sDefaultInterpolator);
}
/**
* 構造方法
* 主要是負責
* 1.初始化默認的插值器 mTimeInterpolator
* 2.初始化聯(lián)合動畫Set mAnimatorSet
* 3.初始化順序或同時播放動畫容器 mAnimatorList
* @param interpolator
*/
private AnimatorSetWrap(TimeInterpolator interpolator) {
mTimeInterpolator = interpolator;
mAnimatorSet = new AnimatorSet();
mAnimatorList=new ArrayList<>(16);
}
/**
* Play動畫的監(jiān)聽啟動方法
* 如果要監(jiān)聽play動畫先調(diào)用這個方法
* @return
*/
public PlayAnimationListener toAddPlayListener(){
playListener=new PlayAnimationListener(this);
return playListener;
}
/**
* Before動畫的監(jiān)聽啟動方法
* 如果要監(jiān)聽Before動畫先調(diào)用這個方法
* @return
*/
public BeforeAnimationListener toAddBeforeListener(){
beforeListener=new BeforeAnimationListener(this);
return beforeListener;
}
/**
* With動畫的監(jiān)聽啟動方法
* 如果要監(jiān)聽With動畫先調(diào)用這個方法
* @return
*/
public WithAnimationListener toAddWithListener(){
withListener=new WithAnimationListener(this);
return withListener;
}
/**
* After動畫的監(jiān)聽啟動方法
* 如果要監(jiān)聽After動畫先調(diào)用這個方法
* @return
*/
public AfterAnimationListener toAddAfterListener(){
afterListener=new AfterAnimationListener(this);
return afterListener;
}
/**
* 順序或同時播放動畫執(zhí)行時的監(jiān)聽方法
* 要先于Then方法進行調(diào)用
* @return
*/
public ThenAnimationListener toAddThenListener(){
thenListener=new ThenAnimationListener(this);
return thenListener;
}
/**
* 順序或者同時播放動畫時的調(diào)用方法
* 在其內(nèi)部生成一個Animator并將該Animator加入到mAnimatorList中備用
* @param view 動畫執(zhí)行的主體View
* @param animName 動畫類型
* @param interpolator 動畫插值器 如果不設置就用默認的
* @param repeatCount 重復次數(shù)
* @param duration 執(zhí)行時間
* @param values 動畫執(zhí)行的值
* @return
*/
public AnimatorSetWrap then(View view, String animName, @Nullable TimeInterpolator interpolator, @Size(min = 0,max=Integer.MAX_VALUE) int repeatCount, @Size(min = 0,max=Integer.MAX_VALUE) int duration, float... values){
LogUtils.e("addThen");
if(view==null){
throw new RuntimeException("view 不能為空");
}
mIsPlaying = true;
mView = view;
ObjectAnimator thenAnimator = ObjectAnimator.ofFloat(view,animName,values);
thenAnimator.setInterpolator(interpolator==null?mTimeInterpolator:interpolator);
thenAnimator.setRepeatCount(repeatCount<0?0:repeatCount);
thenAnimator.setDuration(duration<0?mDuration:duration);
if (thenListener!=null&&thenListener.animatorListener != null) {
thenAnimator.addListener(thenListener.animatorListener);
}
if(thenListener!=null&&thenListener.updateListener!=null){
thenAnimator.addUpdateListener(thenListener.updateListener);
}
if(thenListener!=null&&thenListener.pauseListener!=null){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
thenAnimator.addPauseListener(thenListener.pauseListener);
}else{
throw new RuntimeException("SDK最小要求19");
}
}
mAnimatorList.add(thenAnimator);
return this;
}
public AnimatorSetWrap then(Animator animator) {
mAnimatorList.add(animator);
return this;
}
public AnimatorSetWrap then(AnimatorSetWrap animator) {
mAnimatorList.add(animator.getAnimatorSet());
return this;
}
/**
* AnimatorSet的Play方法,整個動畫過程只能調(diào)用一次
* 并且一旦執(zhí)行play方法將會清除掉mAnimatorList中存儲的順序或同時執(zhí)行的方法實例
* @param view 方法主體
* @param animName 動畫類型
* @param interpolator 插值器
* @param repeatCount 重復次數(shù)
* @param duration 動畫時長
* @param values 動畫執(zhí)行值
* @return
*/
public AnimatorSetWrap play(View view, String animName, @Nullable TimeInterpolator interpolator, @Size(min = 0,max=Integer.MAX_VALUE) int repeatCount, @Size(min = 0,max=Integer.MAX_VALUE) int duration, float... values){
LogUtils.e("play");
if(mIsPlaying){
throw new RuntimeException("AnimatorSetWrap.play()方法只能調(diào)用一次");
}
if(view==null){
throw new RuntimeException("view 不能為空");
}
mIsPlaying = true;
mView = view;
ObjectAnimator playAnimator = ObjectAnimator.ofFloat(view,animName,values);
playAnimator.setInterpolator(interpolator==null?mTimeInterpolator:interpolator);
playAnimator.setRepeatCount(repeatCount<0?0:repeatCount);
playAnimator.setDuration(duration<0?mDuration:duration);
if (playListener!=null&&playListener.animatorListener != null) {
playAnimator.addListener(playListener.animatorListener);
}
if(playListener!=null&&playListener.updateListener!=null){
playAnimator.addUpdateListener(playListener.updateListener);
}
if(playListener!=null&&playListener.pauseListener!=null){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
playAnimator.addPauseListener(playListener.pauseListener);
}else{
throw new RuntimeException("SDK最小要求19");
}
}
mAnimatorList.clear();
mAnimatorBuilder=mAnimatorSet.play(playAnimator);
return this;
}
public AnimatorSetWrap play(Animator animator) {
mAnimatorList.clear();
mAnimatorBuilder = mAnimatorSet.play(animator);
return this;
}
public AnimatorSetWrap play(AnimatorSetWrap animator) {
mAnimatorList.clear();
mAnimatorBuilder = mAnimatorSet.play(animator.getAnimatorSet());
return this;
}
/**
* AnimatorSet的Before方法
* @param view 動畫執(zhí)行的主體View
* @param animName 動畫類型
* @param interpolator 插值器
* @param repeatCount 重復次數(shù)
* @param duration 動畫執(zhí)行時長
* @param values 動畫執(zhí)行數(shù)值
* @return
*/
public AnimatorSetWrap before(View view, String animName,@Nullable TimeInterpolator interpolator, @Size(min = 0,max=Integer.MAX_VALUE) int repeatCount,@Size(min = 0,max=Integer.MAX_VALUE)int duration, float... values){
LogUtils.e("before");
if(view==null){
throw new RuntimeException("view 不能為空");
}
ObjectAnimator beforeAnimator = ObjectAnimator.ofFloat(view,
animName, values).setDuration(duration);
beforeAnimator.setInterpolator(interpolator==null?mTimeInterpolator:interpolator);
beforeAnimator.setRepeatCount(repeatCount<0?0:repeatCount);
beforeAnimator.setDuration(duration<0?mDuration:duration);
if (beforeListener!=null&&beforeListener.animatorListener != null) {
beforeAnimator.addListener(beforeListener.animatorListener);
}
if(beforeListener!=null&&beforeListener.updateListener!=null){
beforeAnimator.addUpdateListener(beforeListener.updateListener);
}
if(beforeListener!=null&&beforeListener.pauseListener!=null){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
beforeAnimator.addPauseListener(beforeListener.pauseListener);
}else{
throw new RuntimeException("SDK最小要求19");
}
}
mAnimatorBuilder = mAnimatorBuilder.before(beforeAnimator);
return this;
}
public AnimatorSetWrap before(Animator animator) {
mAnimatorBuilder = mAnimatorBuilder.before(animator);
return this;
}
public AnimatorSetWrap before(AnimatorSetWrap animator) {
mAnimatorBuilder = mAnimatorBuilder.before(animator.getAnimatorSet());
return this;
}
public AnimatorSetWrap with(View view, String animName,@Nullable TimeInterpolator interpolator,@Size(min = 0,max=Integer.MAX_VALUE) int repeatCount,@Size(min = 0,max=Integer.MAX_VALUE)int duration, float... values){
LogUtils.e("with");
if(view==null){
throw new RuntimeException("view 不能為空");
}
ObjectAnimator withAnimator = ObjectAnimator.ofFloat(view,
animName, values).setDuration(duration);
withAnimator.setInterpolator(interpolator==null?mTimeInterpolator:interpolator);
withAnimator.setRepeatCount(repeatCount<0?0:repeatCount);
withAnimator.setDuration(duration<0?mDuration:duration);
if (withListener!=null&&withListener.animatorListener != null) {
withAnimator.addListener(withListener.animatorListener);
}
if(withListener!=null&&withListener.updateListener!=null){
withAnimator.addUpdateListener(withListener.updateListener);
}
if(withListener!=null&&withListener.pauseListener!=null){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
withAnimator.addPauseListener(withListener.pauseListener);
}else{
throw new RuntimeException("SDK最小要求19");
}
}
mAnimatorBuilder = mAnimatorBuilder.with(withAnimator);
return this;
}
public AnimatorSetWrap with(Animator animator) {
mAnimatorBuilder = mAnimatorBuilder.with(animator);
return this;
}
public AnimatorSetWrap with(AnimatorSetWrap animator) {
mAnimatorBuilder = mAnimatorBuilder.with(animator.getAnimatorSet());
return this;
}
public AnimatorSetWrap after(View view, String animName,@Nullable TimeInterpolator interpolator,@Size(min = 0,max=Integer.MAX_VALUE) int repeatCount,@Size(min = 0,max=Integer.MAX_VALUE) int duration, float... values){
LogUtils.e("after");
if(view==null){
throw new RuntimeException("view 不能為空");
}
ObjectAnimator afterAnimator = ObjectAnimator.ofFloat(view,
animName, values).setDuration(duration);
afterAnimator.setInterpolator(interpolator==null?mTimeInterpolator:interpolator);
afterAnimator.setRepeatCount(repeatCount<0?0:repeatCount);
afterAnimator.setDuration(duration<0?mDuration:duration);
if (afterListener!=null&&afterListener.animatorListener != null) {
afterAnimator.addListener(afterListener.animatorListener);
}
if(afterListener!=null&&afterListener.updateListener!=null){
afterAnimator.addUpdateListener(afterListener.updateListener);
}
if(afterListener!=null&&afterListener.pauseListener!=null){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
afterAnimator.addPauseListener(afterListener.pauseListener);
}else{
throw new RuntimeException("SDK最小要求19");
}
}
mAnimatorBuilder = mAnimatorBuilder.after(afterAnimator);
return this;
}
public AnimatorSetWrap after(Animator animator) {
mAnimatorBuilder = mAnimatorBuilder.after(animator);
return this;
}
public AnimatorSetWrap after(AnimatorSetWrap animator) {
mAnimatorBuilder = mAnimatorBuilder.after(animator.getAnimatorSet());
return this;
}
public AnimatorSetWrap after(long delay) {
mAnimatorBuilder.after(delay);
return this;
}
/**
* 直接執(zhí)行動畫,該動畫操作主要用作執(zhí)行AnimatorSet的組合動畫
* 如果mAnimatorList不為0 則執(zhí)行逐一播放動畫
*/
public void playAnim() {
if(mAnimatorList.size()>0){
readyThen(true);
}
mAnimatorSet.start();
}
/**
* 在一定時長內(nèi)運行完該組合動畫
* 如果mAnimatorList不為0 則執(zhí)行逐一播放動畫
* @param duration 動畫時長
*/
public void playAnim(long duration) {
if(mAnimatorList.size()>0){
readyThen(true);
}
mAnimatorSet.setDuration(duration);
mAnimatorSet.start();
}
/**
* 延遲一定時長播放動畫
* 如果mAnimatorList不為0 則執(zhí)行逐一播放動畫
* @param delay 延遲時長
*/
public void playAnimDelay(long delay) {
if(mAnimatorList.size()>0){
readyThen(true);
}
mAnimatorSet.setStartDelay(delay);
mAnimatorSet.start();
}
/**
* 直接執(zhí)行動畫,該動畫操作主要用作執(zhí)行AnimatorSet的組合動畫
*/
public void playAnim(boolean isSequentially) {
readyThen(isSequentially);
mAnimatorSet.start();
}
/**
* 在一定時長內(nèi)運行完該組合動畫
* @param duration 動畫時長
*/
public void playAnim(boolean isSequentially,long duration) {
readyThen(isSequentially);
mAnimatorSet.setDuration(duration);
mAnimatorSet.start();
}
/**
* 延遲一定時長播放動畫
* @param delay 延遲時長
*/
public void playAnimDelay(boolean isSequentially,long delay) {
readyThen(isSequentially);
mAnimatorSet.setStartDelay(delay);
mAnimatorSet.start();
}
/**
* 順序播放動畫
* @param isSequentially 是逐一播放還是同時播放
*/
private void readyThen(boolean isSequentially){
// 只在第一次啟動時初始化
if (mHasInitThenAnim) {
return;
}
mHasInitThenAnim = true;
if (mAnimatorList.size() > 0) {
AnimatorSet set = new AnimatorSet();
if(isSequentially){
set.playSequentially(mAnimatorList);
}else{
set.playTogether(mAnimatorList);
}
mAnimatorBuilder.before(set);
}
}
/**
* 取消動畫
*/
public void cancel() {
mAnimatorSet.cancel();
mAnimatorList.clear();
}
/**
* 獲取AnimatorSet的實例
* @return
*/
private AnimatorSet getAnimatorSet() {
return mAnimatorSet;
}
/**
* 為AnimatorSet設置監(jiān)聽
* @param listener
* @return
*/
public AnimatorSetWrap setAnimatorSetListener(Animator.AnimatorListener listener) {
mAnimatorSet.addListener(listener);
return this;
}
/**
* 取消AnimatorSet的監(jiān)聽
* @param listener
*/
public void removeSetListner(Animator.AnimatorListener listener) {
mAnimatorSet.removeListener(listener);
}
/**
* 取消全部AnimatorSet的監(jiān)聽
*/
public void removeAllLSetisteners() {
mAnimatorSet.removeAllListeners();
}
/**
* 判斷一個View是否在當前的屏幕中可見(肉眼真實可見)
* @param mView
* @return 返回true則可見
*/
public static boolean isVisibleOnScreen(View mView) {
if (mView == null) {
return false;
}
return mView.getWindowVisibility() == View.VISIBLE
&& mView.getVisibility() == View.VISIBLE && mView.isShown();
}
}
/**
* Play方法對應的ObjectAnimator的監(jiān)聽實例
*/
public static class PlayAnimationListener implements IAnimatorListener<PlayAnimationListener>{
private Animator.AnimatorListener animatorListener;
private ValueAnimator.AnimatorUpdateListener updateListener;
private Animator.AnimatorPauseListener pauseListener;
public AnimatorSetWrap animatorSetWrap;
public PlayAnimationListener(AnimatorSetWrap animatorSetWrap){
this.animatorSetWrap=animatorSetWrap;
}
@Override
public PlayAnimationListener setAnimatorListener(Animator.AnimatorListener animatorListener) {
this.animatorListener=animatorListener;
return this;
}
@Override
public PlayAnimationListener setUpdateListener(ValueAnimator.AnimatorUpdateListener animatorListener) {
this.updateListener=animatorListener;
return this;
}
@Override
public PlayAnimationListener setPauseListener(Animator.AnimatorPauseListener animatorListener) {
this.pauseListener=animatorListener;
return this;
}
@Override
public AnimatorSetWrap and(){
return animatorSetWrap;
}
}
public static class BeforeAnimationListener implements IAnimatorListener<BeforeAnimationListener>{
private Animator.AnimatorListener animatorListener;
private ValueAnimator.AnimatorUpdateListener updateListener;
private Animator.AnimatorPauseListener pauseListener;
public AnimatorSetWrap animatorSetWrap;
public BeforeAnimationListener(AnimatorSetWrap animatorSetWrap){
this.animatorSetWrap=animatorSetWrap;
}
@Override
public AnimatorSetWrap and() {
return animatorSetWrap;
}
@Override
public BeforeAnimationListener setAnimatorListener(Animator.AnimatorListener listener) {
this.animatorListener=listener;
return this;
}
@Override
public BeforeAnimationListener setUpdateListener(ValueAnimator.AnimatorUpdateListener listener) {
this.updateListener=listener;
return this;
}
@Override
public BeforeAnimationListener setPauseListener(Animator.AnimatorPauseListener listener) {
this.pauseListener=listener;
return this;
}
}
public static class WithAnimationListener implements IAnimatorListener<WithAnimationListener>{
private Animator.AnimatorListener animatorListener;
private ValueAnimator.AnimatorUpdateListener updateListener;
private Animator.AnimatorPauseListener pauseListener;
public AnimatorSetWrap animatorSetWrap;
public WithAnimationListener(AnimatorSetWrap animatorSetWrap){
this.animatorSetWrap=animatorSetWrap;
}
@Override
public AnimatorSetWrap and() {
return animatorSetWrap;
}
@Override
public WithAnimationListener setAnimatorListener(Animator.AnimatorListener listener) {
this.animatorListener=listener;
return this;
}
@Override
public WithAnimationListener setUpdateListener(ValueAnimator.AnimatorUpdateListener listener) {
this.updateListener=listener;
return this;
}
@Override
public WithAnimationListener setPauseListener(Animator.AnimatorPauseListener listener) {
this.pauseListener=listener;
return this;
}
}
public static class AfterAnimationListener implements IAnimatorListener<AfterAnimationListener>{
private Animator.AnimatorListener animatorListener;
private ValueAnimator.AnimatorUpdateListener updateListener;
private Animator.AnimatorPauseListener pauseListener;
public AnimatorSetWrap animatorSetWrap;
public AfterAnimationListener(AnimatorSetWrap animatorSetWrap){
this.animatorSetWrap=animatorSetWrap;
}
@Override
public AnimatorSetWrap and() {
return animatorSetWrap;
}
@Override
public AfterAnimationListener setAnimatorListener(Animator.AnimatorListener listener) {
this.animatorListener=listener;
return this;
}
@Override
public AfterAnimationListener setUpdateListener(ValueAnimator.AnimatorUpdateListener listener) {
this.updateListener=listener;
return this;
}
@Override
public AfterAnimationListener setPauseListener(Animator.AnimatorPauseListener listener) {
this.pauseListener=listener;
return this;
}
}
public static class ThenAnimationListener implements IAnimatorListener<ThenAnimationListener>{
private Animator.AnimatorListener animatorListener;
private ValueAnimator.AnimatorUpdateListener updateListener;
private Animator.AnimatorPauseListener pauseListener;
public AnimatorSetWrap animatorSetWrap;
public ThenAnimationListener(AnimatorSetWrap animatorSetWrap){
this.animatorSetWrap=animatorSetWrap;
}
@Override
public AnimatorSetWrap and() {
return animatorSetWrap;
}
@Override
public ThenAnimationListener setAnimatorListener(Animator.AnimatorListener listener) {
this.animatorListener=listener;
return this;
}
@Override
public ThenAnimationListener setUpdateListener(ValueAnimator.AnimatorUpdateListener listener) {
this.updateListener=listener;
return this;
}
@Override
public ThenAnimationListener setPauseListener(Animator.AnimatorPauseListener listener) {
this.pauseListener=listener;
return this;
}
}
/**
* 動畫監(jiān)聽的公用模板接口
* @param <T>
*/
interface IAnimatorListener<T>{
/**
* 設置AnimatorListener的方法
* @param listener
* @return
*/
T setAnimatorListener(Animator.AnimatorListener listener);
/**
* 設置AnimatorUpdateListener的方法
* @param listener
* @return
*/
T setUpdateListener(ValueAnimator.AnimatorUpdateListener listener);
/**
* 設置AnimatorPauseListener的方法
* @param listener
* @return
*/
T setPauseListener(Animator.AnimatorPauseListener listener);
/**
* 橋接動畫監(jiān)聽與動畫工具類的方法
* @return
*/
AnimatorSetWrap and();
}
}
使用方法:
AnimatorUtils.createAnimator().play(viewAnimator,AnimatorUtils.ROTATIONY,null,0,1000,0,360).toAddThenListener().setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
LogUtils.e("then1:"+valueAnimator.getAnimatedValue());
}
}).and().then(viewAnimator, AnimatorUtils.TRANSY, null, -1, -2, 0, 100, 200, 300, 200, 100, 0).toAddThenListener().setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
LogUtils.e("then2:"+valueAnimator.getAnimatedValue());
}
}).and().then(viewAnimator, AnimatorUtils.SCALEX, new LinearInterpolator(), 0, 1000, 0, 10).toAddWithListener().setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
LogUtils.e("with1:"+valueAnimator.getAnimatedValue());
}
}).and().with(viewAnimator, AnimatorUtils.SCALEY, new LinearInterpolator(), 0, 1000, 0, 10).toAddWithListener().setAnimatorListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
LogUtils.e("with2:onAnimationStart");
}
@Override
public void onAnimationEnd(Animator animator) {
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
}).and().with(viewAnimator, AnimatorUtils.ALPHA, new LinearInterpolator(), 0, 1000, 1, 0,1)
//.playSequentially(2000);
.playAnim();
上面的動畫調(diào)用方法是我亂寫的,具體就是為了演示工具類的使用方法,你可以改成自己的調(diào)用方法。
總結
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。
相關文章
Android 中自定義Dialog樣式的Activity點擊空白處隱藏軟鍵盤功能(dialog不消失)
項目中需要開發(fā)帶有EditText的Dialog顯示,要求在編輯完EditText時,點擊Dilog的空白處隱藏軟鍵盤。但是Dialog不會消失。下面通過實例代碼給大家分享實現(xiàn)方法,需要的的朋友參考下吧2017-04-04
Android控件Chronometer定時器的實現(xiàn)方法
這篇文章主要為大家詳細介紹了Android控件Chronometer定時器的實現(xiàn)方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-11-11

