忙了幾天,又到周五了,雖然周五寫bolg好像很少人看,不過無所謂啦。主要總結和自己看看。
本文承接和ys一起學動畫——傳統動畫與屬性動畫(一) 一文繼續介紹關于屬性動畫的一些知識和自己的demo。
本來打算再往demo裡面新加一點内容的。。後來忙了一下,就沒高興寫了。。
好了,進入正題。
屬性動畫
屬性動畫(Property Animation)是一個很強勁的動畫架構,幾乎可以為所有的事物加上動畫效果。你可以定義一個動畫去改變任何對象的屬性,不管該對象是否在螢幕上,都可以進行繪制。一個屬性動畫在某一個時間段,改變的是一個對象的一個屬性值(一個對象的一個字段)。原理就是這樣。
屬性動畫相關的類
ObjectAnimator 對象動畫執行類
ValueAnimator 值動畫執行類
AnimatorSet 一組動畫的執行,有多種方式(一起執行,自定義順序執行等)
AnimtorInflater 加載xml檔案類
TypeEvaluator 類型估值,主要用于設定動畫操作屬性的值
TimeInterpolator 時間插值器
屬性動畫的屬性
Duration:
動畫的持續時間
TimeInterpolation:
用于定義動畫變化率的接口,所有插值器都必須實作此接口,有線性,非線性插值器。
TypeEvaluator:
用于定義屬性值計算方式的接口,有int,float,color類型,根據屬性的起始、結束值和插值一起計算出目前時間的屬性值,可以使用PropertyValuesHolder來捆綁多個值的變化。
Animation sets:
動畫集合,即可以同時對一個對象應用多個動畫,這些動畫可以同時播放也可以對不同動畫設定不同的延遲
Frame refreash delay:
多少時間重新整理一次,即每隔多少時間計算一次屬性值,預設為10ms,最終重新整理時間還受系統程序排程與硬體的影響
Repeat Country and behavoir:
重複次數與方式,如播放3次、5次、無限循環,可以讓此動畫一直重複,或播放完時向反向播放
對于View的屬性來說:
1)translationX 和 translationY:這兩個屬性控制了View所處的位置,
它們的值是由layout容器設定的,是相對于坐标原點(0,0左上角)的一個偏移量。
2)rotation, rotationX 和 rotationY:控制View繞着軸點(pivotX和pivotY)旋轉。它的表現跟Tween Animation中的RotateAnimation不一緻。
RotateAnimation 的旋轉,表現為平面的旋轉
而rotationX、Y 旋轉,是立體的旋轉,預設是以View的中心點,做rotation(x,y)過中心點的直線,面向該直線進行翻轉
3)scaleX 和 scaleY:控制View基于pivotX和pivotY的縮放。
4)pivotX 和 pivotY:旋轉的軸點和縮放的基準點,預設是View的中心點。
5)x 和 y:描述了view在其父容器中的最終位置,是左上角坐标和偏移量(translationX,translationY)的和。
6)aplha:透明度,1是完全不透明,0是完全透明。
具體使用方法
通過調用執行類的ofFloat等方法就可以完成對動畫的初始化,支援的值類型有float,int,keyframe,object以及PropertyValuesHolder。當然,不要忘記調用setDuration和start喔。
1.ObjectAnimator
對象動畫,顧名思義,你可以為其指定一個Target對象,然後對其的某個屬性進行值的變化進而達到動畫效果。使用對象動畫有兩個條件:
①需要變化的屬性必須要有對應的set,get方法;
②指定的屬性必須是UI相關的,不然看不到效果。
//方法一 直接使用,單屬性
ObjectAnimator//
.ofFloat(view, "rotationX", , )//參數:變化的View,變化的屬性,變化的值(為可變長參數)
.setDuration()// 變化的總時長
.start(); // 啟動動畫
欸對了,聽說換成妹子圖才有人氣,我得馬上試試。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISO1IDOyEjMxETMxkDM1EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
//方法二,為動畫設定監聽器,重寫onAnimationUpdate自己實作多個屬性的修改(可對相同的值進行不同處理)
ObjectAnimator anim = ObjectAnimator//
.ofFloat(view, "zhy", F, F)//
.setDuration();//
anim.start();
anim.addUpdateListener(new AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
float cVal = (Float) animation.getAnimatedValue();
view.setAlpha(cVal);
view.setScaleX(cVal);
view.setScaleY(cVal);
}
});
//方法三,使用PropertyValuesHolder 捆綁多個需要改變的屬性字段(可設定不同的值)
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", ,
, );
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", ,
, );
PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", ,
, );
ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY,pvhZ).setDuration().start();
2.ValueAnimator
值動畫僅僅接受值作為參數,不需要之前的屬性名,自然也沒有了必須用對象得有set、get方法的限制。但是往往需要我們自己去實作它的update邏輯。
這裡我實作了一個自由落體效果
/**
* 自由落體
* @param view
*/
public void verticalRun( View view)
{
ValueAnimator animator = ValueAnimator.ofFloat(f,f);
animator.setTarget(mBlueBall1);
animator.setDuration().start();
animator.setInterpolator(new LinearInterpolator());
animator.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
// TODO Auto-generated method stub
Log.i(TAG,"drop start");
}
@Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
Log.i(TAG,"drop repeat");
}
@Override
public void onAnimationEnd(Animator animation) {
// TODO Auto-generated method stub
Log.i(TAG,"drop end");
}
@Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
Log.i(TAG,"drop cancel");
}
});
animator.addUpdateListener(new AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
//自己實作邏輯
float temp = (Float) animation.getAnimatedValue();
mBlueBall1.setTranslationY((float)(mScreenHeight - mBlueBall.getHeight()) * temp * temp);
}
});
}
還有一個抛物線效果
/**
* 抛物線
* @param view
*/
public void paowuxian(View view)
{
ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setDuration();
valueAnimator.setObjectValues(new PointF(, ),new PointF(mScreenWidth - mBlueBall.getWidth(),mScreenHeight - mBlueBall1.getHeight()));
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setEvaluator(new TypeEvaluator<PointF>()
{
// fraction = t / duration
@Override
public PointF evaluate(float fraction, PointF startValue,
PointF endValue)
{
float maxa = (float) (endValue.x - startValue.x);
float maxb = (float) (endValue.y - startValue.y);
PointF point = new PointF();
point.x = maxa * fraction;
point.y = maxb * (fraction * fraction);
return point;
}
});
valueAnimator.start();
valueAnimator.addUpdateListener(new AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
PointF point = (PointF) animation.getAnimatedValue();
mBlueBall.setTranslationX(point.x);
mBlueBall.setTranslationY(point.y);
}
});
}
兩球同時落地(需要都使用線性時間插值器,才能達到這樣的效果):
3.AnimatorSet
一組動畫的執行,有多種方式(一起執行,自定義順序執行等)
簡單易懂的代碼:
private void onebyone() {
// TODO Auto-generated method stub
float cx = mBlueBall.getX();
ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",
, );
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",
, );
ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall,
"x", cx , );
ObjectAnimator anim4 = ObjectAnimator.ofFloat(mBlueBall,
"x", cx);
/**
* anim1,anim2,anim3,anim4依次執行
*/
AnimatorSet animSet = new AnimatorSet();
animSet.play(anim1).before(anim2);
animSet.play(anim2).before(anim3);
animSet.play(anim4).after(anim3);
animSet.setDuration();
animSet.start();
}
private void together() {
// TODO Auto-generated method stub
ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",
, ,);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",
, ,);
ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall, "alpha",
, ,);
AnimatorSet animSet = new AnimatorSet();
animSet.setDuration();
animSet.setInterpolator(new LinearInterpolator());
//一起執行
animSet.playTogether(anim1, anim2,anim3);
animSet.start();
}
(稍後會補充一些關于LayoutAnimator的内容,插值器前面已經講了這邊我就不再贅述了)
小結
其實屬性動畫用起來沒有那麼困難,做出來效果也蠻不錯的,這裡放出demo給大家下載下傳。以後的demo都免費提供吧 。
Demo下載下傳