您的位置:首页 > 移动开发 > Android开发

Android -- NineOldAndroids animation 封装

2016-04-16 13:26 567 查看


1.概述

  说起空间动态、微博的点赞效果,网上也是很泛滥,各种实现与效果一大堆。而详细实现的部分,讲述的也是参差不齐,另一方面估计也有很多大侠也不屑一顾,觉得完全没必要单独开篇来写和讲解吧。毕竟,也就是两个view和一些简单的动画效果罢了。

  单若是只讲这些,我自然也是不愿花这番功夫的。虽然自己很菜,可也不甘于太菜。所以偶尔看到些好东西,可以延伸学写下,我还是很情愿拿出来用用,顺带秀一秀逼格什么的。

  不扯太多,先说说今天实现点赞效果用到的自以为不错的两个点:

AndroidViewAnimations 基于nineoldandroids封装的android动画简易类库。究竟有多简单呢,就像这样

AnimHelper.with(new PulseAnimator()).duration(1000).playOn(imageView);

作用: 在imageView上使用PulseAnimator这个动画效果,播放一秒。


1.1 动画库的封装和快速框架

  提到动画,Android本身自带的动画类Animation已经做到支持3.0及以上了,虽然也做了很好的封装,但是做起复杂动画来还是不够像上边那样简洁。在关于动画兼容方面,github上的大牛Jake Wharton又做了一套动画开源库NineOldAndroids,效果很好而且支持3.0级以前的版本,确实很值得称赞。而在此基础上,有很多高手又做了二次封装,实现了复杂动画,同时保证方便简洁,而且通用性和扩展性更高。我们这里的动画使用的就是这样一个简单的封装。

  比如,要在XXView上时用XXAnimator这样的动画,持续Duration秒。就这么一行代码:

AnimHelper.with(new SlideOutUpAnimator()).duration(1000).playOn(textView);

  来看一下基于NineOldAndroids的ViewAnimations具体实现。


1. 首先定义一个基本动画效果类BaseViewAnimator

  这个BaseViewAnimator动画类使用一个动画集合AnimatorSet,包装成单个动画类似的用法,并定义了一个abstract方法prepare():

package com.xiaobai.mizar.utils.anim;

import android.view.View;
import android.view.animation.Interpolator;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorSet;
import com.nineoldandroids.view.ViewHelper;

/**
* Author: walid
* Date : 2016/4/16 11:30
*/
public abstract class BaseViewAnimator {

public static final long DURATION = 1000;

private AnimatorSet animatorSet;
private long mDuration = DURATION;

{
animatorSet = new AnimatorSet();
}

protected abstract void prepare(View target);

public BaseViewAnimator setTarget(View target) {
reset(target);
prepare(target);
return this;
}

public void animate() {
start();
}

/**
* reset the view to default status
*
* @param target
*/
public void reset(View target) {
ViewHelper.setAlpha(target, 1);
ViewHelper.setScaleX(target, 1);
ViewHelper.setScaleY(target, 1);
ViewHelper.setTranslationX(target, 0);
ViewHelper.setTranslationY(target, 0);
ViewHelper.setRotation(target, 0);
ViewHelper.setRotationY(target, 0);
ViewHelper.setRotationX(target, 0);
ViewHelper.setPivotX(target, target.getMeasuredWidth() / 2.0f);
ViewHelper.setPivotY(target, target.getMeasuredHeight() / 2.0f);
}

/**
* start to animate
*/
public void start() {
animatorSet.setDuration(mDuration);
animatorSet.start();
}

public BaseViewAnimator setDuration(long duration) {
mDuration = duration;
return this;
}

public BaseViewAnimator setStartDelay(long delay) {
getAnimatorAgent().setStartDelay(delay);
return this;
}

public long getStartDelay() {
return animatorSet.getStartDelay();
}

public BaseViewAnimator addAnimatorListener(Animator.AnimatorListener l) {
animatorSet.addListener(l);
return this;
}

public void cancel() {
animatorSet.cancel();
}

public boolean isRunning() {
return animatorSet.isRunning();
}

public boolean isStarted() {
return animatorSet.isStarted();
}

public void removeAnimatorListener(Animator.AnimatorListener l) {
animatorSet.removeListener(l);
}

public void removeAllListener() {
animatorSet.removeAllListeners();
}

public BaseViewAnimator setInterpolator(Interpolator interpolator) {
animatorSet.setInterpolator(interpolator);
return this;
}

public long getDuration() {
return mDuration;
}

public AnimatorSet getAnimatorAgent() {
return animatorSet;
}

}


  复杂动画效果基类BaseViewAnimator使用一个AnimatorSet集合来添加各种动画 ,并绑定到目标targetView ,使用 prepare(View target) 的abstract方法供其子类实现具体的动画效果。


2. 其次基于这个类实现我们的各种动画效果XXAnimator

 当我们要实现具体的动画效果时,可以直接继承这个类并实现prepaer方法。比如这里定义的上划消失SlideOutUpAnimator 和放大回缩动画PulseAnimator

package com.xiaobai.mizar.utils.anim;

import android.view.View;
import com.nineoldandroids.animation.ObjectAnimator;

/**
* Author: walid
* Date : 2016/4/16 11:33
* 放大效果
*/
public class PulseAnimator extends BaseViewAnimator {
@Override
public void prepare(View target) {
getAnimatorAgent().playTogether(
ObjectAnimator.ofFloat(target, "scaleY", 1, 1.3f, 1),
ObjectAnimator.ofFloat(target, "scaleX", 1, 1.3f, 1)
);
}
}


package com.xiaobai.mizar.utils.anim;

import android.view.View;
import android.view.ViewGroup;
import com.nineoldandroids.animation.ObjectAnimator;

/**
* Author: walid
* Date : 2016/4/16 11:33
* 上划消失(飘+1)
*/
public class SlideOutUpAnimator extends BaseViewAnimator {
@Override
public void prepare(View target) {
ViewGroup parent = (ViewGroup) target.getParent();
getAnimatorAgent().playTogether(
ObjectAnimator.ofFloat(target, "alpha", 1, 0),
ObjectAnimator.ofFloat(target, "translationY", 0, -parent.getHeight() / 2)
);
}
}


 上边两种动画效果就是对BaseViewAnimator的两种实现,动画本身使用的库是NineOldAndroids。


3. 最后封装一个动画管理工具类AnimHelper供外部使用

 首先定义了一个静态类,使用helper来实例化这个静态类,并设置各个参数选项。
package com.xiaobai.mizar.utils.anim;

import android.view.View;
import android.view.animation.Interpolator;
import com.nineoldandroids.animation.Animator;

import java.util.ArrayList;
import java.util.List;

/**
* Author: walid
* Date : 2016/4/16 11:32
*/
public class AnimHelper {

private static final long DURATION = BaseViewAnimator.DURATION;
private static final long NO_DELAY = 0;

/**
* 实例化得到AnimationComposer的唯一接口
*/
public static AnimationComposer with(BaseViewAnimator animator) {
return new AnimationComposer(animator);
}

/**
* 定义与动画效果相关联的各种参数,
* 使用这种方法可以保证对象的构建和他的表示相互隔离开来
*/
public static final class AnimationComposer {

private List<Animator.AnimatorListener> callbacks = new ArrayList<>();
private BaseViewAnimator animator;
private long duration = DURATION;
private long delay = NO_DELAY;
private Interpolator interpolator;
private View target;

private AnimationComposer(BaseViewAnimator animator) {
this.animator = animator;
}

public AnimationComposer duration(long duration) {
this.duration = duration;
return this;
}

public AnimationComposer delay(long delay) {
this.delay = delay;
return this;
}

public AnimationComposer interpolate(Interpolator interpolator) {
this.interpolator = interpolator;
return this;
}

public AnimationComposer withListener(Animator.AnimatorListener listener) {
callbacks.add(listener);
return this;
}

public AnimManager playOn(View target) {
this.target = target;
return new AnimManager(play(), this.target);
}

private BaseViewAnimator play() {
animator.setTarget(target);
animator.setDuration(duration)
.setInterpolator(interpolator)
.setStartDelay(delay);

if (callbacks.size() > 0) {
for (Animator.AnimatorListener callback : callbacks) {
animator.addAnimatorListener(callback);
}
}

animator.animate();
return animator;
}
}

/**
* 动画管理类
*/
public static final class AnimManager {

private BaseViewAnimator animator;
private View target;

private AnimManager(BaseViewAnimator animator, View target) {
this.target = target;
this.animator = animator;
}

public boolean isStarted() {
return animator.isStarted();
}

public boolean isRunning() {
return animator.isRunning();
}

public void stop(boolean reset) {
animator.cancel();
if (reset) {
animator.reset(target);
}
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: