android 属性动画入门

前面关于tween动画写了2篇博客,如果那2篇博客都看懂了,估计Tween动画理解使用起来问题就不大,之前也说了Tween动画的缺点就是在交互上有bug,今天就讲下属性动画,属性动画就能解决Tween动画交互上的问题,由于下周工作上很忙,估计要花一周时间把这篇博客写完,一些常见的动画demo,都在写出来,希望每个人都能看的懂,切入正题,


属性动画英文叫Property Animator,它包括ValueAnimator和ObjectAnimator,我们先看ValueAnimator这个类,从类名字直观的就是叫值动画,对吧,那么这和Tween动画不同的是Tween动画是叫view animation,作用于控件上的,如果看过ValueAnimator类的源码就知道它是继承了Animator这个类,现在看下Animator类的源码,看看它给我们提供了什么方法让我们去调用,这个类的源码是我把注释删除了,代码量很少,才200多行

package android.animation;
import android.content.res.ConstantState;
import java.util.ArrayList;
public abstract class Animator implements Cloneable {
    /**
     * The set of listeners to be sent events through the life of an animation.
     */
    ArrayList<AnimatorListener> mListeners = null;
    /**
     * The set of listeners to be sent pause/resume events through the life
     * of an animation.
     */
    ArrayList<AnimatorPauseListener> mPauseListeners = null;
    /**
     * Whether this animator is currently in a paused state.
     */
    boolean mPaused = false;
  
    int mChangingConfigurations = 0;
    private AnimatorConstantState mConstantState;
    public void start() {
    }
    public void cancel() {
    }

    public void end() {
    }
    public void pause() {
        if (isStarted() && !mPaused) {
            mPaused = true;
            if (mPauseListeners != null) {
                ArrayList<AnimatorPauseListener> tmpListeners =
                        (ArrayList<AnimatorPauseListener>) mPauseListeners.clone();
                int numListeners = tmpListeners.size();
                for (int i = 0; i < numListeners; ++i) {
                    tmpListeners.get(i).onAnimationPause(this);
                }
            }
        }
    }
    public void resume() {
        if (mPaused) {
            mPaused = false;
            if (mPauseListeners != null) {
                ArrayList<AnimatorPauseListener> tmpListeners =
                        (ArrayList<AnimatorPauseListener>) mPauseListeners.clone();
                int numListeners = tmpListeners.size();
                for (int i = 0; i < numListeners; ++i) {
                    tmpListeners.get(i).onAnimationResume(this);
                }
            }
        }
    }
    public boolean isPaused() {
        return mPaused;
    }
    public abstract long getStartDelay();
    public abstract void setStartDelay(long startDelay);
    public abstract Animator setDuration(long duration);
    public abstract long getDuration();
    public abstract void setInterpolator(TimeInterpolator value);
    public TimeInterpolator getInterpolator() {
        return null;
    }
    public abstract boolean isRunning();
    public boolean isStarted() {
        // Default method returns value for isRunning(). Subclasses should override to return a
        // real value.
        return isRunning();
    }
    public void addListener(AnimatorListener listener) {
        if (mListeners == null) {
            mListeners = new ArrayList<AnimatorListener>();
        }
        mListeners.add(listener);
    }
    public void removeListener(AnimatorListener listener) {
        if (mListeners == null) {
            return;
        }
        mListeners.remove(listener);
        if (mListeners.size() == 0) {
            mListeners = null;
        }
    } 
    public ArrayList<AnimatorListener> getListeners() {
        return mListeners;
    }
    public void addPauseListener(AnimatorPauseListener listener) {
        if (mPauseListeners == null) {
            mPauseListeners = new ArrayList<AnimatorPauseListener>();
        }
        mPauseListeners.add(listener);
    } 
    public void removePauseListener(AnimatorPauseListener listener) {
        if (mPauseListeners == null) {
            return;
        }
        mPauseListeners.remove(listener);
        if (mPauseListeners.size() == 0) {
            mPauseListeners = null;
        }
    }
    public void removeAllListeners() {
        if (mListeners != null) {
            mListeners.clear();
            mListeners = null;
        }
        if (mPauseListeners != null) {
            mPauseListeners.clear();
            mPauseListeners = null;
        }
    }

    public int getChangingConfigurations() {
        return mChangingConfigurations;
    }
    public void setChangingConfigurations(int configs) {
        mChangingConfigurations = configs;
    } 
    public void appendChangingConfigurations(int configs) {
        mChangingConfigurations |= configs;
    }
    public ConstantState<Animator> createConstantState() {
        return new AnimatorConstantState(this);
    }
    @Override
    public Animator clone() {
        try {
            final Animator anim = (Animator) super.clone();
            if (mListeners != null) {
                anim.mListeners = new ArrayList<AnimatorListener>(mListeners);
            }
            if (mPauseListeners != null) {
                anim.mPauseListeners = new ArrayList<AnimatorPauseListener>(mPauseListeners);
            }
            return anim;
        } catch (CloneNotSupportedException e) {
           throw new AssertionError();
        }
    }
    public void setupStartValues() {
    }
    public void setupEndValues() {
    }


    public void setTarget(Object target) {
    }
  
    public boolean canReverse() {
        return false;
    }
    /**
     * @hide
     */
    public void reverse() {
        throw new IllegalStateException("Reverse is not supported");
    }
    public static interface AnimatorListener { 
        void onAnimationStart(Animator animation);
        void onAnimationEnd(Animator animation);
        void onAnimationCancel(Animator animation);
        void onAnimationRepeat(Animator animation);
    }

    public static interface AnimatorPauseListener {
        void onAnimationPause(Animator animation);
        void onAnimationResume(Animator animation);
    }
    public void setAllowRunningAsynchronously(boolean mayRunAsync) {
        // It is up to subclasses to support this, if they can.
    }
    private static class AnimatorConstantState extends ConstantState<Animator> {
        final Animator mAnimator;
        int mChangingConf;
        public AnimatorConstantState(Animator animator) {
            mAnimator = animator;
            // ensure a reference back to here so that constante state is not gc'ed.
            mAnimator.mConstantState = this;
            mChangingConf = mAnimator.getChangingConfigurations();
        }
        @Override
        public int getChangingConfigurations() {
            return mChangingConf;
        }
        @Override
        public Animator newInstance() {
            final Animator clone = mAnimator.clone();
            clone.mConstantState = this;
            return clone;
        }
    }
}

通过看它的源码发现Animator是一个抽象类,既然它是抽象类,那么一定存在抽象的方法,现在就把几个抽象方法提出来

public abstract void setStartDelay(long startDelay); 这是延迟几秒开始执行动画

public abstract long getStartDelay();获取动画延迟执行的时间,单位为毫秒

 public abstract Animator setDuration(long duration); 设置动画执行的时间 单位为毫秒

 public abstract long getDuration();获取动画执行的时间

public abstract void setInterpolator(TimeInterpolator value);设置动画插值器

 public abstract boolean isRunning();动画是否在执行

下面是非抽象函数并且是空实现的

 public void start() {} 动画开始

  public void cancel() {}取消执行动画

public void end() {}结束动画执行

 public void setTarget(Object target) {}设置动画的标记

下面是非空实现方法:

public void pause() {}动画暂停的方法

public void resume() {}动画重新执行

public boolean isPaused() {}动画是否暂停了,默认返回值为false

public TimeInterpolator getInterpolator() {}  返回动画插值器对象,默认返回为null

public boolean isStarted() {} 动画是否执行了,默认返回值是调用了isRunning()方法,而这个方法又是抽象的,需要子类去实现,

public void addListener(AnimatorListener listener) {
    if (mListeners == null) {
        mListeners = new ArrayList<AnimatorListener>();
    }
    mListeners.add(listener);
}
这是添加动画监听的方法,它是用一个List集合去维护了所添加的监听器,而AnimatorListener是一个接口,如下:

public static interface AnimatorListener {
    /**
     * <p>Notifies the start of the animation.</p>
     *
     * @param animation The started animation.
     */
    void onAnimationStart(Animator animation);

    /**
     * <p>Notifies the end of the animation. This callback is not invoked
     * for animations with repeat count set to INFINITE.</p>
     *
     * @param animation The animation which reached its end.
     */
    void onAnimationEnd(Animator animation);

    /**
     * <p>Notifies the cancellation of the animation. This callback is not invoked
     * for animations with repeat count set to INFINITE.</p>
     *
     * @param animation The animation which was canceled.
     */
    void onAnimationCancel(Animator animation);

    /**
     * <p>Notifies the repetition of the animation.</p>
     *
     * @param animation The animation which was repeated.
     */
    void onAnimationRepeat(Animator animation);
}
这个接口分别定义了四个方法依次是动画开始,结束,取消,重复等回调接口,

public void removeListener(AnimatorListener listener) {
    if (mListeners == null) {
        return;
    }
    mListeners.remove(listener);
    if (mListeners.size() == 0) {
        mListeners = null;
    }
}
这个是移除一个动画监听,

public ArrayList<AnimatorListener> getListeners() {
    return mListeners;
}
这是获取所有监听动画

public void addPauseListener(AnimatorPauseListener listener) {
    if (mPauseListeners == null) {
        mPauseListeners = new ArrayList<AnimatorPauseListener>();
    }
    mPauseListeners.add(listener);
}
这是添加一个暂停动画监听的方法,而AnimatorPauseListener是一个接口

public static interface AnimatorPauseListener {
    /**
     * <p>Notifies that the animation was paused.</p>
     *
     * @param animation The animaton being paused.
     * @see #pause()
     */
    void onAnimationPause(Animator animation);

    /**
     * <p>Notifies that the animation was resumed, after being
     * previously paused.</p>
     *
     * @param animation The animation being resumed.
     * @see #resume()
     */
    void onAnimationResume(Animator animation);
}
分别定义了动画暂停和重新执行的回调方法

public void removePauseListener(AnimatorPauseListener listener) {
    if (mPauseListeners == null) {
        return;
    }
    mPauseListeners.remove(listener);
    if (mPauseListeners.size() == 0) {
        mPauseListeners = null;
    }
}
这是移除一个暂停动画的监听

public void removeAllListeners() {
    if (mListeners != null) {
        mListeners.clear();
        mListeners = null;
    }
    if (mPauseListeners != null) {
        mPauseListeners.clear();
        mPauseListeners = null;
    }
}
这是移除所有动画的监听,包括动画开始和结束的监听和暂停的监听

下面就开始讲ValueAnimator类的一些使用了,

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ValueAnimator animator = ValueAnimator.ofInt(0,100);
        animator.setDuration(1000);
        animator.start();
    }
}
这是一个平移动画,但我并没有把这个动画作用于某一个控件上,那这个动画到底有没有执行呢?我们知道动画都有监听的方法,

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        int curValue = (int)animation.getAnimatedValue();
        Log.d(TAG,"curValue:"+curValue);
    }
});
animation.getAnimatedValue()方法是返回动画的属性值,默认返回值是Object,但是我们传入的是int值,所以就可以强转成int值了,通过打印的log分析:

07-10 05:05:24.945 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:0
07-10 05:05:25.098 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:5
07-10 05:05:25.285 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:24
07-10 05:05:25.325 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:29
07-10 05:05:25.355 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:34
07-10 05:05:25.365 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:36
07-10 05:05:25.385 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:39
07-10 05:05:25.405 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:42
07-10 05:05:25.415 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:44
07-10 05:05:25.435 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:47
07-10 05:05:25.445 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:50
07-10 05:05:25.465 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:52
07-10 05:05:25.475 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:55
07-10 05:05:25.495 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:57
07-10 05:05:25.515 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:60
07-10 05:05:25.525 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:62
07-10 05:05:25.548 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:65
07-10 05:05:25.565 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:67
07-10 05:05:25.582 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:70
07-10 05:05:25.598 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:72
07-10 05:05:25.615 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:74
07-10 05:05:25.627 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:77
07-10 05:05:25.648 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:79
07-10 05:05:25.665 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:81
07-10 05:05:25.676 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:83
07-10 05:05:25.698 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:85
07-10 05:05:25.715 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:87
07-10 05:05:25.732 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:88
07-10 05:05:25.748 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:90
07-10 05:05:25.765 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:91
07-10 05:05:25.777 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:93
07-10 05:05:25.798 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:94
07-10 05:05:25.815 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:95
07-10 05:05:25.825 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:96
07-10 05:05:25.848 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:97
07-10 05:05:25.865 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:98
07-10 05:05:25.882 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:98
07-10 05:05:25.898 1178-1178/com.example.valueanimatordemo D/MainActivity:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值