android动画封装,Android属性动画封装,快速构建动画

Android实现动画效果的方式主要有帧动画、补间动画、属性动画。关于安桌动画的基础知识可以查看这篇文章Android属性动画完全解析

这里我要讲的是如何快速构建出一个动画效果,如下图:

0818b9ca8b590ca3270a3433284dd417.png

如果我们用属性动画实现,其中点击男性头像后的动画效果的代码如下:

// 男生头像移到上面,水平居中

float centerX = -mPortraitMale.getX()+ (Util.getScreenWidth(this) / 2 - mPortraitMale.getWidth() / 2);

ObjectAnimator portraitMaleTransX = ObjectAnimator.ofFloat(mPortraitMale,

"translationX",0,centerX);

portraitMaleTransX.setDuration(500);

ObjectAnimator portraitMaleTransY = ObjectAnimator.ofFloat(

mPortraitMale, "translationY", 0,

-(mPortraitMale.getY() - mPortraitFemal.getY()));

portraitMaleTransY.setDuration(500);

// 女生头像移出右边,并逐渐淡出

ObjectAnimator portraitFemaleTrans = ObjectAnimator.ofFloat(

mPortraitFemal, "translationX", 0, Util.getScreenWidth(this)

- mPortraitFemal.getX());

portraitFemaleTrans.setDuration(500);

ObjectAnimator portraitFemaleAlpha = ObjectAnimator.ofFloat(

mPortraitFemal, "alpha", 1, 0.2f);

portraitFemaleAlpha.setDuration(500);

// 头像列表的白色背景升起

ObjectAnimator shieldTrans = ObjectAnimator.ofFloat(mPortraitShield,

"translationY", mPortraitShield.getHeight(), 0);

shieldTrans.setDuration(200);

shieldTrans.addListener(new BaseAnimatorListener() {

@Override

public void onAnimationStart(Animator animation) {

mPortraitShield.setVisibility(View.VISIBLE);

}

public void onAnimationEnd(Animator animation) {

mScrollView.setVisibility(View.VISIBLE); // 显示头像列表

}

});

// 头像列表从底部升起

ObjectAnimator listTrans = ObjectAnimator.ofFloat(mScrollView,

"translationY", mScrollView.getHeight(), 0);

listTrans.setDuration(500);

AnimatorSet listAnimSet = new AnimatorSet();

listAnimSet.play(shieldTrans).before(listTrans);

AnimatorSet animatorSet = new AnimatorSet();

// 把男生女生头像移到相应位置后,再弹出头像列表

animatorSet.play(portraitMaleTransX).with(portraitMaleTransY)

.with(portraitFemaleTrans).with(portraitFemaleAlpha)

.before(listAnimSet);

animatorSet.start();

其实这个效果不难实现,可代码看上去却比较凌乱臃肿,所以,我对属性动画进行了封装,封装后的工具类为AnimatorUtil。使用方法介绍:

1.调用AnimatorSetWrap animSetWrap = AnimatorUtil.createAnimator(obj); 获取属性动画的封装对象,obj为动画起初要操作的对象

2.animSetWrap.play(duration,  propertyName, values) \\设置第一个要执行的动画

.with(duration,  propertyName, values) \\ 该动画跟play中的动画同时执行

.with(obj, duration,  propertyName, values) \\ obj为要操作的对象,该对象动画跟play中的动画同时执行

.then(obj, duration,  propertyName, values) \\ play动画执行完后,执行第一个then中的动画

.then(obj, duration, listener, propertyName, values) \\ 第1个then动画执行完后,执行第2个then中的动画,listener为动画监听器

.then(obj, duration,  propertyName, values) \\ 第2个then动画执行完后,执行第3个then中的动画,依次类推,链式构建动画

.start(); \\ 执行动画

AnimatorSet animSet = animSetWrap.getAnimatorSet(); \\ 获取被封装的Animtor对象

3.另外还有before()和after()方法,跟自带的属性动画的方法一样,before里的动画在play动画执行完后执行,after动画执行完后才执行play动画,即在play动画之前执行。AnimatorSetWrap中的每个动画方法都有多个重载版本,可以传入操作对象、监听器等,如上所示,方法直接可以链式调用。

AnimatorUtil的核心方法then()的实现在于,用一个数组存储所有的then动画,在play()方法内部添加监听器,当play动画结束后执行第一个then动画;then()方法内部对动画添加了监听器,当then动画结束时执行下一个then动画,依次类推,使动画按照顺序执行。关键代码如下:

public AnimatorSetWrap play(Object obj, long duration,

AnimatorListener listener, String propertyName, float... values) {

ObjectAnimator animator = ObjectAnimator.ofFloat(obj,

propertyName, values).setDuration(duration);

if (listener != null) {

animator.addListener(listener);

}

mAnimatorsThen.clear(); // 清空

// play动画执行完之后执行第一个then()动画

animator.addListener(new AnimatorListenerThen(mAnimatorsThen.size()));

mAnimatorSetBuilder = mAnimatorSet.play(animator);

return this;

}

public AnimatorSetWrap then(Object obj, long duration,

AnimatorListener listener, String propertyName, float... values) {

ObjectAnimator animator = ObjectAnimator.ofFloat(obj,

propertyName, values).setDuration(duration);

if (listener != null) {

animator.addListener(listener);

}

mAnimatorsThen.add(animator);

animator.addListener(new AnimatorListenerThen(mAnimatorsThen.size()));

return this;

}

private class AnimatorListenerThen implements AnimatorListener {

private int mNextAnim = -1; // 下一个动画在mAnimators中的索引

public AnimatorListenerThen(int nextAnimIndex) {

mNextAnim = nextAnimIndex;

}

public void onAnimationEnd(Animator animation) {

// 执行下一个动画

if (mNextAnim < mAnimatorsThen.size()) {

mAnimatorsThen.get(mNextAnim).start();

}

}

下面是使用AnimatorUtil工具类构建上图动画的代码:

float portraitMaleX = -mPortraitMale.getX()

+ (Util.getScreenWidth(this) / 2 - mPortraitMale

.getWidth() / 2);

float portraitMaleY = -(mPortraitMale.getY() - mPortraitFemal

.getY());

AnimatorUtil

.createAnimator(mPortraitMale)

.play(500, "translationX", 0,

portraitMaleX)

.with(500, "translationY", 0,

portraitMaleY)

.with(mPortraitFemal, 500,

"translationX", 0,

Util.getScreenWidth(this) - mPortraitFemal.getX())

.with(mPortraitFemal, 500, "alpha",

1, 0.2f)

.then(mPortraitShield,

200,

new BaseAnimatorListener() {

public void onAnimationStart(

Animator animation) {

mPortraitShield.setVisibility(View.VISIBLE);

}

public void onAnimationEnd(

Animator animation) {

mScrollView.setVisibility(View.VISIBLE);

}

}, "translationY", mPortraitShield.getHeight(),

0)

.then(mScrollView, 500,"translationY", mScrollView.getHeight(), 0)

.start();

可以看出代码简洁明了,构建动画便捷,如果要新增加动画效果,在相应方法后面加入动画即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值