Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 屬性動畫 詳解

Android 屬性動畫 詳解

編輯:關於Android編程

認識屬性動畫

傳統動畫Animation平移方法的實現
TranslateAnimation animation = new TranslateAnimation(x軸初始位置,x軸終止位置,y軸初始位置,y軸終止位置);
animation.setDuration(1000);//設置持續時間,ms單位
animation.setFillAfter(true);//設置動畫結束後狀態,true為保持最終狀態

imageView.startAnimation(animation);//為控件添加要執行的動畫

傳統動畫的局限性,只是重繪了動畫,改變了顯示位置,但是真正的響應位置沒有發生任何改變,並不適合做具有交互的動畫效果
傳統動畫框架的局限性:只是重繪了View,但是View原來相應事件的位置並沒有改變,這樣就會使得View在動畫結束後,點擊View沒有相應,而點擊View原來的位置才有響應,這就是一個很詭異的事情。

屬性動畫Animator與傳統動畫Animation

package com.example.animationtest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


}
public void click(View view){
Toast.makeText(this, "click", Toast.LENGTH_SHORT).show();
}
public void move(View view){
TranslateAnimation animation = new TranslateAnimation(0, 200, 0, 0);
animation.setDuration(2000);
animation.setFillAfter(true);
ImageView imageView = (ImageView) findViewById(R.id.imageView1);
imageView.startAnimation(animation);
}


}

ObjectAnimator

一、ObjectAnimator屬性動畫
1.ObjectAnimator.ofFloat(view,”“,float,float).setDuration(1000).start();
第二個參數:
translationX、translationY偏移量
rotation旋轉
X、Y偏移至
2.同時作用三個屬性動畫
PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat(“rotation”,0,360f);
ObjectAnimator.ofPropertyValuesHolder(view,p1,p2,p3).setDuration(1000).start();

二、AnimatorSet
1.同時作用三個屬性動畫
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view,”rotation”,0,360F);
AnimatorSet set = new AnimatorSet();
set.playTogether(animator1,animator2,animator3);
set.start();
2.順次播放動畫
set.playSequentially(animator1,animator2,animator3);
3.組合動畫
set.play(animator2).with(animator3);
set.play(animator1).after(animator2);
動畫二和動畫三同時播放,結束後播放動畫一
Animator同樣支持AnimatorSet,增加動畫組合的多樣性
playSequentially:按順序進行動畫的播放
playTogether:一起執行所選的動畫效果
還可以進行屬性集合的詳細控制
set.play(動畫2).with(動畫3);
set.play(動畫1).after(動畫2);
屬性動畫平移的實現方法
ObjectAnimatior.ofFloat(imageView,”translationX”,0F,200f).setDuration(1000).start();
//ofFloat方法(要操作的對象,”要操作的元素”,變化范圍,變化范圍).設置持續時間.開始執行
要操作的元素只要包含get和set方法都可以使用屬性動畫,例如
translationX/translationY:X/Y軸的偏移量
X/Y:X/Y的最終量
rotation:旋轉,從0度開始
ObjectAnimatior.ofFloat()方法實現的動畫是同時進行的,同時操作多個屬性的動畫可以使用ofPropertyValuesHolder方法
PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat(“rotation”,0,360F);
PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat(“translationX”,0,360F);
PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat(“translationY”,0,360F);
ObjectAnimatior.ofPropertyValuesHolder(imageView,p1,p2,p3).setDuration(1000).start();
1.ObjectAnimation.ofFloat(動作對象,String類型動作屬性,float類型動作數值);
動作屬性:”translationX”,”X”,”rotation”
2.多個屬性動畫可以同時進行,為了優化動作屬性可以用以下方法:
PropertyValuesHolder p1=PropertyValuesHolder.ofFloat(“rotation”,0,360f);
ObjectAnimator.ofPropertyValuesHolder(對象, p1,p2,p3).setDuration(1000).start();
3.用set方法:
ObjectAnimator animator1=ObjectAnimator.ofFloat(對象,”屬性名”,Values);
AnimatorSet set=new AnimatorSet();
set.playTogether(animator1,animator2,animator3);同時運行
set.playSequentially(animator1,animator2,animator3);連續運行
set.play(animator2).with(animator3);同時進行
set.play(animator1).after(animator3);animator1在animator3後運行
Animation平移動畫 耗CPU Google提供了很多例子
TranslateAnimation animation=new TranslateAnimation(x0,x1,y0,y1)
animation.setDuration(1000)設置時間
animation.setFillAfter(true)保留平移後位置
imageview.setAnimation(animation);
屬性動畫:監聽事件也跟著一起移動了
ObjectAnimator.ofFloat(imageview,”translationX”,0F,200F).setDuration(1000).start()

只要是有get和set的屬性都可以添加屬性動畫
—-屬性動畫是異步執行的,多寫幾行一起動 亦可傳遞PropertyValueHolder來保存屬性的變化,然後一起傳進去ObjectAnimation.ofPropertyValueHolder(imageview,p1,p2,p3)
translationX改為X就是絕對位置
—————rotation就是旋轉

使用PropertyValuesHolder實現組合動畫效果。
PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("rotation",0,360F);
PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("translationX",0,360F);
PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("translationY",0,360F);
ObjectAnimatior.ofPropertyValuesHolder(imageView,p1,p2,p3).setDuration(1000).start();
·使用AnimatorSet來完成 {
AnimatorSet set = new AnimatorSet();
ObjectAnimator animator1 = ObjectAnimator.offloat(imageView, "rotation", 0f, 200f);
ObjectAnimator animator2 = ObjectAnimator.offloat(imageView, "translationX", 0f, 200f);
ObjectAnimator animator3 = ObjectAnimator.offloat(imageView, "translationY", 0f, 200f);
set.playTogether(animator1,animator2,animator3); // 動畫一起播放
// set.playSequentially(animator1,animator2,animator3); // 順序播放動畫
// 控制動畫之間的播放順序
// set.play(animator2).with(animator3); // 先X和Y一起平移
// set.play(animator1).after(animator3); // 平移完成之後旋轉
set.setDuration(1000);
set.start();
}

動畫監聽事件

分享一下個人實現的環形菜單效果,按鈕是發散成圓排布的。
float y = (float) (r * Math.sin((Math.PI / 2) / (res.length - 2) * (i - 1)));
float x = (float) (r * Math.cos((Math.PI / 2) / (res.length - 2) * (i - 1)));
ObjectAnimator animator = ObjectAnimator.ofFloat(viewList.get(i), “translationY”,
0f, -y);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(viewList.get(i), “translationX”,
0f, x);
x,y是通過數學知識計算出來的,改變x,y 的正負值,菜單彈出的方向也可以改變,其他的代碼和老師的相同。
動畫是速度interpolator,他可以定義動畫的速度變化,從而實現更加復雜的動畫效果。設置interpolator的方法:
ObjectAnimator的setInterpolator()方法,參數可以傳遞各種各樣的interpolator,比如:
objectAnimator.setInterpolator(new BounceInterpolator());
animator.addListener(new AnimatorListenerAdapter); //只要重寫一個事件
animator.setStartDelay(x);//依次彈出x為間隔毫秒
setInterpolator(new XXX);//設置動畫的速度變換
alpha 透明度
rotation z軸旋轉
rotationX x軸旋轉
rotationY y軸旋轉
translationX x水平偏移
translationY y水平偏移
ScaleX x軸縮放
ScaleY y軸縮放
AccelerateDecelerateInterpolator 在動畫開始與結束的地方速率改變比較慢,在中間的時候加速

AccelerateInterpolator 在動畫開始的地方速率改變比較慢,然後開始加速

AnticipateInterpolator 開始的時候向後然後向前甩

AnticipateOvershootInterpolator 開始的時候向後然後向前甩一定值後返回最後的值

BounceInterpolator 動畫結束的時候彈起

CycleInterpolator 動畫循環播放特定的次數,速率改變沿著正弦曲線

DecelerateInterpolator 在動畫開始的地方快然後慢

LinearInterpolator 以常量速率改變

OvershootInterpolator 向前甩一定值後再回到原來位置
alpha 透明度
rotation z軸旋轉
rotationX x軸旋轉
rotationY y軸旋轉
translationX x水平偏移
translationY y水平偏移
ScaleX x軸縮放
ScaleY y軸縮放

Tips:
1.ObjectAnimator.ofFloat(view,"alpha",0F,1F);

一、給Animator添加監聽
1.animator.addListener(new Animator.AnimatorListener(){...});
2.animator.addListener(new AnimatorListenerAdapter(){...});不需重寫所有事件方法

二、例子
1.animator.setStartDelay(300);動畫延時0.3s
2.animator.setInterpolator(new BounceInterpolator());差值器(彈性)
ObjectAnimator animator = ObjectAnimator.ofFloat(view,"alpha",0,1f).setDuration(1000);
animator.addListener(new Animator.AnimatorListener() {
public void onAnimationStart(Animator animation) {
}
public void onAnimationEnd(Animator animation) {
}
public void onAnimationCancel(Animator animation) {
}
public void onAnimationRepeat(Animator animation) {
}
});
//選擇監聽事件
animator.addListener(new AnimatorListenerAdapter(){

});

//差值器(均速度,加速度,拋物線)內置九種差值器
animator,setInterpolator(new BounceInterpolator());

public class ListenForAnEvent extends Activity implements OnClickListener {

    private int[] ids = {R.id.a, R.id.b, R.id.c, R.id.d, R.id.e, R.id.f, R.id.g, R.id.h };
    private List imageViewList = new ArrayList();
    private boolean flag = false;
    private int r = 250;

    /*
     * (非 Javadoc) Description:
     * @see android.app.Activity#onCreate(android.os.Bundle)
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_listen_event);
        for (int i = 0; i < ids.length; i++) {
            ImageView imageView = (ImageView) findViewById(ids[i]);
            imageViewList.add(imageView);
            imageView.setOnClickListener(this);
        }
    }

    /*
     * (非 Javadoc) Description:
     * @see android.view.View.OnClickListener#onClick(android.view.View)
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.a:
            if (!flag) {
                startAnimator();
            } else {
                closeAnimator();
            }
            break;

        default:
            Toast.makeText(ListenForAnEvent.this, "Image=" + v, Toast.LENGTH_SHORT).show();
            break;
        }
    }

    /**
     * @Description (關閉動畫)
     */
    private void closeAnimator() {
        for (int i = 1; i < ids.length; i++) {
            float y = (float) (r * Math.sin((Math.PI / 2) / (ids.length / 2) * (i - 1)));
            float x = (float) (r * Math.cos((Math.PI / 2) / (ids.length / 2) * (i - 1)));
            ObjectAnimator animatorX = ObjectAnimator.ofFloat(imageViewList.get(i), "translationX", x, 0);
            ObjectAnimator animatorY = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", y, 0);
            AnimatorSet animator = new AnimatorSet();
            animator.playTogether(animatorX, animatorY);
            // ObjectAnimator animator = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", i * 100F, 0);
            animator.setDuration(1000);
            animator.setInterpolator(new BounceInterpolator());
            animator.setStartDelay(i * 1000);
            animator.start();
            flag = false;
        }

    }

    /**
     * @Description (開啟動畫)
     */
    private void startAnimator() {
        for (int i = 1; i < ids.length; i++) {
            float y = (float) (r * Math.sin((Math.PI / 2) / (ids.length / 2) * (i - 1)));
            float x = (float) (r * Math.cos((Math.PI / 2) / (ids.length / 2) * (i - 1)));
            Log.d("jia", "y=" + y);
            ObjectAnimator animatorX = ObjectAnimator.ofFloat(imageViewList.get(i), "translationX", 0, x);
            ObjectAnimator animatorY = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", 0, y);
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.playTogether(animatorX, animatorY);

            // ObjectAnimator animatorSet = ObjectAnimator.ofFloat(imageViewList.get(i), "translationY", 0, i * 100F);
            animatorSet.setDuration(2000);
            animatorSet.setInterpolator(new OvershootInterpolator());
            animatorSet.setStartDelay(i * 1000);
            animatorSet.start();
            flag = true;
        }
    }
}

ValueAnimator

ObjectAnimator常用屬性:
translationX、translationY ;rotation、rotationX、rotationY ;scaleX、scaleY ; X、Y ; alpha
常用方法、類:
ValueAnimator、ObjectAnimator、AnimatorUpdateListener、AnimatorListenerAdapter、PropertyValuesHolder、AnimatorSet、TypeEvalueators、Interpolators
2.ofObject()自定義
ValueAnimator animator = ValueAnimator.ofObject(new TypeEvaluator(){
//fraction時間因子,0~1
public Object evaluate(float fraction, PointF startValue, PointF endValue){
return null;
}
});

三、總結
1.ObjectAnimator常用屬性:
translationX、translationY ;rotation、rotationX、rotationY ;scaleX、scaleY ; X、Y ; alpha
2.常用方法、類
ValueAnimator、ObjectAnimator、AnimatorUpdateListener、AnimatorListenerAdapter、PropertyValuesHolder、AnimatorSet、TypeEvalueators、Interpolators
在屬性動畫框架中最常用的方法和類:
ValueAnimator
ObjectAnimator
AnimatorUpdateListener
AnimatorListenerAdapter
PropertyValuesHolder
AnimatorSet
TypeEvaluators
Interpolators
一、ValueAnimator
1.ValueAnimator本身並不會作用於任何一個屬性,也不會提供任何一個動畫,它是一個數值發生器
2.計算屬性動畫中每一步的具體動畫效果
3.如何產生值:
ValueAnimator會根據動畫已進行的時間與其持續的總時間的比值產生一個0~1的時間因子,有了這樣一個時間因子,經過相應的變換,就可以根據startValue()和endValue()來生產中間的相應值。同時,通過插值器的使用,可以進一步地控制每一個時間因子產生值的變化速率。
4.ObjectAnimator繼承自ValueAnimator

二、ValueAnimator的使用
1.ofInt()
ValueAnimator animator = ValueAnimator.ofInt(0,100);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener{
public void onAnimationUpdate(ValueAnimator animation){
Integer value = (Integer)animation.getAnimatedValue();
}
});
下面的例子是利用ValueAnimator實現一個Button上數字的改變。ValueAnimator是一個timing engine,他負責進行動畫時候變化的中間值的計算,比如這個例子,我們就是想看在5000毫秒內,如果一個值從0變化到100,並且進行勻速變化的話是什麼情況(我們沒有為ValueAnimator設置Interpolator,所以默認的就是勻速變化)。通過addUpdateListener()方法我們可以監聽到ValueAnimator在計算和改變值的時候每一幀數據,所以在這個監聽器的回調方法中我們就可以通過getAnimatedValue()來獲取每一幀的值,從而將它設置到UI上,實現我們想要的效果。所以如果我們不想要動畫效果,只關心動畫中各個值的變化,我們想獲取這些變化的值在動畫中的中間值和這些值的變化效果,我們就可以考慮使用ValueAnimator(這個類的名字也取的很貼切)。
ValueAnimator數值發生器
產生數值
ofInt(1,100)
ValueAnimator的addUpdateListener()監聽獲取每一步產生的數值
—————-在匿名內部類中通過getAnimatedValue()方法獲得數值
自定義數值發生器:
ValueAnimator.ofObject(new TypeEvaluator<可指定泛型>(){實現evaluate(0-1的時間因子,開始,結束值)方法})
一、ValueAnimator
1.ValueAnimator本身並不會作用於任何一個屬性,也不會提供任何一個動畫,它是一個數值發生器
2.計算屬性動畫中每一步的具體動畫效果
3.如何產生值:
ValueAnimator會根據動畫已進行的時間與其持續的總時間的比值產生一個0~1的時間因子,有了這樣一個時間因子,經過相應的變換,就可以根據startValue()和endValue()來生產中間的相應值。同時,通過插值器的使用,可以進一步地控制每一個時間因子產生值的變化速率。
4.ObjectAnimator繼承自ValueAnimator

二、ValueAnimator的使用
1.ofInt()
ValueAnimator animator = ValueAnimator.ofInt(0,100);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener{
public void onAnimationUpdate(ValueAnimator animation){
Integer value = (Integer)animation.getAnimatedValue();
}
});

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved