Android 屬性動畫(二)
上一篇 Android 屬性動畫(一) 介紹了Property Animator 的基本用法。今天繼續瞭解Property Animator 的Evaluator、Interpolator 和 xml 檔案定義Animator 的相關知識和用法。
Evaluator 求值器
直接貼原始碼:
public interface TypeEvaluator<T> {
/**
* 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 * (x1 - x0)</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.
* @param endValue The end value.
* @return A linear interpolation between the start and end values, given the
* <code>fraction</code> parameter.
*/
public T evaluate(float fraction, T startValue, T endValue);
}
原始碼很簡短,就一個方法,預設實現就是 根據fraction 通過 result = x0 + t * (x1 - x0) 公式計算返回一箇中間值。
那麼 fraction 這個引數是多少呢?通過ValueAnimator 的setEvaluator() 方法找到原始碼:
boolean animationFrame(long currentTime) {
boolean done = false;
switch (mPlayingState) {
case RUNNING:
case SEEKED:
float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
if (mDuration == 0 && mRepeatCount != INFINITE) {
// Skip to the end
mCurrentIteration = mRepeatCount;
if (!mReversing) {
mPlayingBackwards = false;
}
}
if (fraction >= 1f) {
if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE)
{
// Time to repeat
if (mListeners != null) {
int numListeners = mListeners.size();
for (int i = 0; i < numListeners; ++i) {
mListeners.get(i).onAnimationRepeat(this);
}
}
if (mRepeatMode == REVERSE) {
mPlayingBackwards = !mPlayingBackwards;
}
mCurrentIteration += (int) fraction;
fraction = fraction % 1f;
mStartTime += mDuration;
// Note: We do not need to update the value of mStartTimeCommitted here
// since we just added a duration offset.
} else {
done = true;
fraction = Math.min(fraction, 1.0f);
}
}
if (mPlayingBackwards) {
fraction = 1f - fraction;
}
animateValue(fraction);
break;
}
return done;
}
void animateValue(float fraction) {
fraction = mInterpolator.getInterpolation(fraction);
mCurrentFraction = fraction;
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
mValues[i].calculateValue(fraction);
}
if (mUpdateListeners != null) {
int numListeners = mUpdateListeners.size();
for (int i = 0; i < numListeners; ++i) {
mUpdateListeners.get(i).onAnimationUpdate(this);
}
}
}
在 ValueAnimator 類中有兩個方法,可以看到在 animationFrame 方法就是 得到一個已完成時間在總時長的比例值(0~1)並賦值給 fraction,在 animateValue 方法中 呼叫了 mInterpolator.getInterpolation() (就是 插值器,後面會介紹) 目的就是修正 fraction 。所以我們知道 fraction 是一個0~1 的值。現在看下自定義Evaluator 的程式碼:
//定義了一個 PointF 型別的 Evaluator ,實現 view 的拋物線變化
//預設 TypeEvaluator View 在X,Y方向都是勻速的。
//自定義後,View的Y方向是變速的。
ValueAnimator valueAnimator = ValueAnimator.ofObject(new TypeEvaluator<PointF>(){
@Override public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
// y 方向是一個變速 PointF point = new PointF();
point.x = startValue.x + fraction * (endValue.x - startValue.x) ;
point.y = (float) (startValue.y + Math.pow(fraction , 2) * (endValue.y - startValue.y));
return point;
}},
new PointF(0,0),new PointF(400,1000));
valueAnimator.setDuration(3000);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.start();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointF point = (PointF) animation.getAnimatedValue();
animView.setX(point.x);
animView.setY(point.y);
}});
valueAnimator.start();
Interpolator 插值器
本來想寫下Interpolayor的原始碼分析的,但看到一篇 Interpolayor的分析文章後,感覺自己也不會寫的比這個好,所以還是不寫了,借鑑和學習這篇文章 李海珍大神的 android動畫(一)Interpolator。膜拜!!!
一下是從 大神文章中摘抄的部分,圖文並茂,講解很詳細,大家學習下!
二:簡單插值器分析
** 注意下面的圖,對應你腦海中的插值的大小應該是斜率。**
package android.view.animation;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
/**
*
* 一個開始很慢然後不斷加速的插值器。
* <hr/>
* An interpolator where the rate of change starts out slowly and
* and then accelerates.
*
*/
public class AccelerateInterpolator implements Interpolator {
private final float mFactor; private final double mDoubleFactor;
public AccelerateInterpolator() {
mFactor = 1.0f;
mDoubleFactor = 2.0;
}
/**
* Constructor
*
* @param factor
* 動畫的快慢度。將factor設定為1.0f會產生一條y=x^2的拋物線。增加factor到1.0f之後為加大這種漸入效果(也就是說它開頭更加慢,結尾更加快)
* <br/>Degree to which the animation should be eased. Seting
* factor to 1.0f produces a y=x^2 parabola(拋物線). Increasing factor above
* 1.0f exaggerates the ease-in effect (i.e., it starts even * slower and ends evens faster)
*/
public AccelerateInterpolator(float factor) {
mFactor = factor;
mDoubleFactor = 2 * mFactor;
}
public AccelerateInterpolator(Context context, AttributeSet attrs) {
TypedArray a =context.obtainStyledAttributes(attrs,com.android.internal.R.styleable.AccelerateInterpolator);
mFactor = a.getFloat(com.android.internal.R.styleable.AccelerateInterpolator_factor, 1.0f);
mDoubleFactor = 2 * mFactor;
a.recycle();
}
@Override
public float getInterpolation(float input) {
if (mFactor == 1.0f) {
return input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
}
加速的快慢度由引數fractor決定。
當fractor值為1.0f時,動畫加速軌跡相當於一條y=x^2的拋物線。如下圖:
當fractor不為1時,軌跡曲線是y=x^(2*fractor)(0<x<=1)的曲線。
示例:當fractor為4時,插值器的加速軌跡曲線如下圖:
如果你在使用AccelerateInterpolator時,想要那種一開始很慢,然後突然就很快的加速的動畫效果的話。
就將fractor設定大點。
你可以到這裡除錯下你想要的拋物線效果:http://www.wolframalpha.com/input/?i=x%5E%282*3%29%280%3Cx%3C%3D1%29
Android提供的一個不同factor的加速插值器:
(1)accelerate_cubic, factor為1.5
xml 檔案定義Animator
大家應該都在xml 檔案定義過 幀動畫 和 補間動畫。今天,我們就在xml中定義屬性動畫,來看看有什麼區別。
先在 res 檔案下建立 anmator 資料夾,在建立 res/animator/animator_set.xml 檔案:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together">
<objectAnimator
android:duration="1000"
android:propertyName="scaleX"
android:valueFrom="1"
android:valueTo="0.5">
</objectAnimator>
<objectAnimator
android:duration="1000"
android:propertyName="scaleY"
android:valueFrom="1"
android:valueTo="0.5">
</objectAnimator>
</set>
這個檔案是實現 同時縮放XY軸的動畫集合,我們可以看到 set 標籤 動畫集合有個
android:ordering 屬性,android:ordering 有兩個值 :together(同時執行),sequentially (順序執行)。接下來在程式碼中載入動畫:
// 載入動畫
Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator_set);
//設定 縮放的中心點
animView.setPivotX(0);
animView.setPivotY(0);
//顯示的呼叫invalidate
animView.invalidate();
anim.setTarget(animView);
anim.start();
如上,將 animView 設為target 就可以了。 當然,縮放 和旋轉都可以設定中心點的,我們將縮放的中心點設定在了 (0,0),預設都是在物件中心點。如果,只想實現單個動畫,可以在xml 中去掉 set標籤。
下面是總結
今天介紹了 Property Animator 的 Evaluator 、Interpolator 和 xml 定義,我們可以跟愉快的實現酷炫的動畫啦。當然,在看了Interpolator 的文章後,還是佩服的五體投地的,我們要努力,像大神看齊!
接下來,我會總結下 ** 佈局動畫(Layout Animations)** ,然後就是 屬性動畫實戰啦,233333。fighting!!!
原始碼,原始碼中還有我之前寫的防直播打賞禮物動畫效果。歡迎大家指教!
相關文章
- android屬性動畫Android動畫
- Android 動畫之屬性動畫Android動畫
- Android 屬性動畫實戰Android動畫
- 【Android 動畫】動畫詳解之屬性動畫(三)Android動畫
- 【Android 動畫】動畫詳解之屬性動畫(五)Android動畫
- Android 動畫詳解:屬性動畫、View 動畫和幀動畫Android動畫View
- Android 自定義View:屬性動畫(六)AndroidView動畫
- Android 顏色漸變 屬性動畫Android動畫
- Android備忘錄《屬性動畫-ValueAnimator》Android動畫
- 屬性動畫動畫
- SVG 動畫 fill 屬性SVG動畫
- SVG restart 動畫屬性SVGREST動畫
- SVG restart動畫屬性SVGREST動畫
- 初識屬性動畫——使用Animator建立動畫動畫
- 屬性動畫與差值器動畫
- 安卓Property Animator動畫詳解(二)-自定義屬性安卓動畫
- HenCoder Android 自定義 View 1-6: 屬性動畫(上手篇)AndroidView動畫
- Android解析WindowManager(二)Window的屬性Android
- Android繪製(三):Path結合屬性動畫,讓圖示動起來!Android動畫
- SVG accumulate和additive動畫屬性SVG動畫
- Android屬性動畫基礎:你是否真的瞭解插值器(TimeInterpolator)Android動畫
- 屬性動畫-波紋擴散WaveView動畫View
- 三談屬性動畫——Keyframe以及ViewPropertyAnimator動畫View
- 檢視屬性+物件動畫元件ViewPropertyObjectAnimator物件動畫元件ViewObject
- 【Android 動畫】動畫詳解之插值器(二)Android動畫
- Android 《CardView 屬性》AndroidView
- Android XML 屬性AndroidXML
- 屬性動畫 ValueAnimator 執行原理全解析動畫
- 帶有活力的屬性動畫原始碼分析與實戰——Android高階UI動畫原始碼AndroidUI
- CSS動畫屬性關鍵幀keyframes全解析CSS動畫
- SpringBoot配置屬性二Spring Boot
- APK瘦身屬性——android:extractNativeLibsAPKAndroid
- Android動畫Android動畫
- android 動畫Android動畫
- Android自動化-如何獲取檢視元素屬性?Android
- 多條目載入(附帶透明的屬性動畫)動畫
- Android 樣式屬性的使用Android
- Android之動畫Android動畫
- Android 動畫初探Android動畫