上一篇總結了View動畫相關的知識,這一節主要學習Android種的屬性動畫–也是目前最經常使用的一種動畫。它能實作View動畫所不能實作的一些動畫效果。
1.簡介
屬性動畫(
Property Animation
)是在 Android 3.0(API 11)後才提供的一種全新動畫模式,它大大解決傳統動畫的局限性,如:經過動畫後,其點選事件的響應區域依然未改變。它具有相當高的靈活性,我們可以通過反射機制動态的設定某一個類種的屬性進而達到動畫的效果。
作用對象:任意
Java
對象
具體邏輯:此圖引用自感謝作者
其繼承結構:
而我們平常主要使用的是
ValueAnimator
與
ObjectAnimator
,下面主要介紹它的使用。
2.TypeEvaluator-估值器
如果想要自定義複雜的動畫效果,那麼我們必須要了解TypeEvaluator。什麼是TypeEvaluator呢?
簡單來說,就是告訴動畫系統如何從初始值過度到結束值。
ValueAnimator
内部自帶
FloatEvaluator
。我們通過源碼可以發現其實作了·
TypeEvaluator
接口,并且重寫了
evaluate方法
。
/**
* This evaluator can be used to perform type interpolation between <code>float</code> values.
*/
public class FloatEvaluator implements TypeEvaluator<Number> {
/**
* This function returns the result of linearly interpolating the start and end values, with
* <code>fraction</code> representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
* and <code>t</code> is <code>fraction</code>.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value; should be of type <code>float</code> or
* <code>Float</code>
* @param endValue The end value; should be of type <code>float</code> or <code>Float</code>
* @return A linear interpolation between the start and end values, given the
* <code>fraction</code> parameter.
*/
public Float evaluate(float fraction, Number startValue, Number endValue) {
float startFloat = startValue.floatValue();
return startFloat + fraction * (endValue.floatValue() - startFloat);
}
}
變量 | 含義 |
---|---|
fraction | 表示動畫完成度 |
startValue | 表示動畫開始值 |
endValue | 表示動畫結束值 |
3.ValueAnimator的基本使用
看一個簡單的Demo,學習基本的使用:
//ValueAnimator
//0-2-1之間在5s内重複執行2次,延時一秒開始執行
//final ValueAnimator animator = ValueAnimator.ofFloat(0f,2f,1f);
final ValueAnimator animator = ValueAnimator.ofInt(0, 2, 1);
//動畫持續時長
animator.setDuration(5000);
//重複次數
animator.setRepeatCount(2);
//延遲多久後開始執行
animator.setStartDelay(1000);
//動畫重複模式,RESTART代表重新播放 REVERSE代表倒序播放
animator.setRepeatMode(ValueAnimator.RESTART);
//進度更新的監聽
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.e("wdl", "onAnimationUpdate: " + (int) animation.getAnimatedValue());
}
});
基本的方法有:
3.ObjectAnimator的基本使用
ObjectAnimator.ofXxx(Object target,String propertyName,Args...value)
,第一個參數代表目标對象,第二個參數為想要操作的屬性名,最後一個為一個可變長參數。
//獨立動畫效果
//透明度
final ObjectAnimator alphaObjectAnimator = ObjectAnimator
.ofFloat(imageView,"alpha",1f,0f,1f);
//旋轉
final ObjectAnimator rotateObjectAnimator = ObjectAnimator
.ofFloat(imageView,"rotation",0f,360f);
//縮放
final ObjectAnimator scaleXObjectAnimator = ObjectAnimator
.ofFloat(imageView,"scaleX",1f,2f,1f);
final ObjectAnimator scaleYObjectAnimator = ObjectAnimator
.ofFloat(imageView,"scaleY",1f,2f,1f);
float translateY = imageView.getTranslationY();
Log.e("wdl", "translateY: "+translateY);
final ObjectAnimator translateYObjectAnimator = ObjectAnimator.
ofFloat(imageView,"translationY",
translateY,-600f,translateY);
// alphaObjectAnimator.setDuration(5000);
// rotateObjectAnimator.setDuration(5000);
// scaleXObjectAnimator.setDuration(5000);
// scaleYObjectAnimator.setDuration(5000);
// translateYObjectAnimator.setDuration(5000);
//FloatEvaluator
//組合動畫
final AnimatorSet animatorSet = new AnimatorSet();
//play方法傳回一個Builder對象
//樹結構
//after 就是在目前的基礎上添加一個父親節點 ,隻能添加一個父親節點(子節點隻能有一個父親節點)
//before 在目前基礎上添加孩子節點,可以添加2個子節點
animatorSet.play(translateYObjectAnimator).with(alphaObjectAnimator)
.after(rotateObjectAnimator)
.before(scaleXObjectAnimator).before(scaleYObjectAnimator);
animatorSet.setDuration(5000);
//添加所有的監聽
animatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
//根據需求重寫監聽方法
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
}
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
}
});
其中
AnimatorSet
,組合動畫有四個方法:
//play方法傳回一個Builder對象
//樹結構
//after 就是在目前的基礎上添加一個父親節點 ,隻能添加一個父親節點(子節點隻能有一個父親節點)
//before 在目前基礎上添加孩子節點,可以添加2個子節點
animatorSet.play(translateYObjectAnimator).with(alphaObjectAnimator)
.after(rotateObjectAnimator)
.before(scaleXObjectAnimator).before(scaleYObjectAnimator);
animatorSet.setDuration(5000);
檢視相關源碼:
/**
* Sets up the given animation to play when the animation supplied in the
* {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
* ends.
*
* @param anim The animation that will play when the animation supplied to the
* {@link AnimatorSet#play(Animator)} method ends.
*/
public Builder before(Animator anim) {
Node node = getNodeForAnimation(anim);
mCurrentNode.addChild(node);
return this;
}
/**
* Sets up the given animation to play when the animation supplied in the
* {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
* to start when the animation supplied in this method call ends.
*
* @param anim The animation whose end will cause the animation supplied to the
* {@link AnimatorSet#play(Animator)} method to play.
*/
public Builder after(Animator anim) {
Node node = getNodeForAnimation(anim);
mCurrentNode.addParent(node);
return this;
}
可以看出,使用的是樹結構:
方法 | 作用 |
---|---|
play | 方法傳回一個Builder對象 |
with | 與play種的動畫一起執行 |
after | 就是在目前的基礎上添加一個父親節點 ,隻能添加一個父親節點(子節點隻能有一個父親節點),此動畫在前面的動畫之前執行 |
before | 在目前基礎上添加孩子節點,可以添加2個子節點,在前面的動畫之後執行 |
4.總結一下常用的方法
方法 | 作用 |
---|---|
setDuration | 動畫持續時長 |
setRepeatCount | 動畫重複次數 |
setStartDelay | 動畫延時開始的時長 |
setRepeatMode | 動畫重複模式 |
addUpdateListener | 動畫監聽 |
5.XML中使用
動畫相關檔案位于
res/animator/
下。
基本使用:(基本的屬性作用與Java代碼中的類似)
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially">
<!-- android:ordering sequentially按照xml檔案中的先後順序執行 together同時執行 -->
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:valueFrom="-500"
android:valueTo="0"
android:valueType="floatType" />
<set android:ordering="together">
<objectAnimator
android:duration="3000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" />
<set android:ordering="sequentially">
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType" />
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
</set>
</set>
</set>
Java中使用:
Animator xmlAnimator = AnimatorInflater.loadAnimator(this,R.animator.animations);
//将動畫設定給對應的view
xmlAnimator.setTarget(imageView);
xmlAnimator.start();
本文參考:
https://blog.csdn.net/guolin_blog/article/details/43816093
https://www.jianshu.com/p/2412d00a0ce4
https://blog.csdn.net/guolin_blog/article/details/43536355
https://blog.csdn.net/guolin_blog/article/details/43816093