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

屬性動畫的基本使用

編輯:關於Android編程

屬性動畫簡介

Android開發過程中,適當的使用一些動畫可以讓自己的應用看起來更棒更炫。最初的時候Google為了實現動畫,主要提供了兩種基本動畫:
幀動畫:將一個完整的動畫拆分成一張張單獨的圖片,然後再將它們連貫起來進行播放
補間動畫:無需逐一定義每一幀,只要定義開始、結束的幀,和指定動畫持續時間。
到了Android3.0,Google推出了一種新的動畫模式,屬性動畫。屬性動畫是對補間動畫的進一步完善和強化。

為什麼引入屬性動畫:

關於這個問題,可以借鑒一下郭霖的一段話:
補間動畫機制其實還算是比較健全的,可以讓我們實現View的移動、縮放、旋轉和淡入淡出效果,並且我們還可以借助AnimationSet來將這些動畫效果組合起來使用,除此之外還可以通過配置Interpolator來控制動畫的播放速度等等等等。那麼這裡大家可能要產生疑問了,既然之前的動畫機制已經這麼健全了,為什麼還要引入屬性動畫呢?
其實上面所謂的健全都是相對的,如果你的需求中只需要對View進行移動、縮放、旋轉和淡入淡出操作,那麼補間動畫確實已經足夠健全了。但是很顯然,這些功能是不足以覆蓋所有的場景的,一旦我們的需求超出了移動、縮放、旋轉和淡入淡出這四種對View的操作,那麼補間動畫就不能再幫我們忙了,也就是說它在功能和可擴展方面都有相當大的局限性,那麼下面我們就來看看補間動畫所不能勝任的場景。
注意上面我在介紹補間動畫的時候都有使用“對View進行操作”這樣的描述,沒錯,補間動畫是只能夠作用在View上的。也就是說,我們可以對一個Button、TextView、甚至是LinearLayout、或者其它任何繼承自View的組件進行動畫操作,但是如果我們想要對一個非View的對象進行動畫操作,抱歉,補間動畫就幫不上忙了。可能有的朋友會感到不能理解,我怎麼會需要對一個非View的對象進行動畫操作呢?這裡我舉一個簡單的例子,比如說我們有一個自定義的View,在這個View當中有一個Point對象用於管理坐標,然後在onDraw()方法當中就是根據這個Point對象的坐標值來進行繪制的。也就是說,如果我們可以對Point對象進行動畫操作,那麼整個自定義View的動畫效果就有了。顯然,補間動畫是不具備這個功能的,這是它的第一個缺陷。
然後補間動畫還有一個缺陷,就是它只能夠實現移動、縮放、旋轉和淡入淡出這四種動畫操作,那如果我們希望可以對View的背景色進行動態地改變呢?很遺憾,我們只能靠自己去實現了。說白了,之前的補間動畫機制就是使用硬編碼的方式來完成的,功能限定死就是這些,基本上沒有任何擴展性可言。
最後,補間動畫還有一個致命的缺陷,就是它只是改變了View的顯示效果而已,而不會真正去改變View的屬性。什麼意思呢?比如說,現在屏幕的左上角有一個按鈕,然後我們通過補間動畫將它移動到了屏幕的右下角,現在你可以去嘗試點擊一下這個按鈕,點擊事件是絕對不會觸發的,因為實際上這個按鈕還是停留在屏幕的左上角,只不過補間動畫將這個按鈕繪制到了屏幕的右下角而已。正是因為這些原因,功能更為完善和強大的屬性動畫就應運而生了。

繼承關系

繼承關系

從圖中可以看出,補間動畫主要是使用android.view.animation.Animation包下面的五個類來實現不同的動畫效果;而屬性動畫主要是使用android.animation.Animator的ValueAnimator以及其子類ObjectAnimator來實現不同的動畫效果。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxzdHJvbmc+VmFsdWVBbmltYXRvcjwvc3Ryb25nPg0KPHA+tNPK9NDUtq+7rc/gudi21M/ztcS8zLPQudjPtb/J0tS/tLP2o6xWYWx1ZUFuaW1hdG9yysexyL3PusvQxLXE0ru49sDgoaO52be9zsS1tbXEvenJ3MrHo7p0aGlzIGNsYXNzIHByb3ZpZGVzIGEgc2ltcGxlIHRpbWluZyBlbmdpbmUgZm9yIHJ1bm5pbmcgYW5pbWF0aW9ucyB3aGljaCBjYWxjdWxhdGUgYW5pbWF0ZWQgdmFsdWVzIGFuZCBzZXQgdGhlbSBvbiB0YXJnZXQgb2JqZWN0cyZoZWxsaXA70rK+zcrHy7VWYWx1ZUFuaW1hdG9yttTP88Tasr/OrLPWwcvSu7j2vPK1pbXEyrG85NL9x+ajrLzGy+PUy9DQtq+7rbXEvt/M5da1zazKsbDRy/zDx8no1sO4+MS/seq21M/zoaPNqMvXtcS9sr7NysejrFZhbHVlQW5pbWF0b3K1xMTasr/KudPD0rvW1sqxvOTRrbu3tcS7+tbGwLS8xsvj1rXT69a11q685LXEtq+7rbn9tsmjrM7Sw8fWu9Do0qq9q7P1yrzWtbrNveHK+Na1u/LV39bQvOTWtczhuam4+FZhbHVlQW5pbWF0b3KjrLKix9LJ6NbDtq+7rdTL0NDKsbOko6zEx8O0VmFsdWVBbmltYXRvcr7Nu+HX1LavzeqzybTTs/XKvNa1xr27rLn9tsm1vb3hyvjWtdXi0fm1xNCnufuho7b4x9KjrFZhbHVlQW5pbWF0b3K7ubi61PC53MDttq+7rbXEsqW3xbTOyv2horKlt8XEo8q9oaLS1LywttS2r7utyejWw7zgzP3G97XIoaPLtbXEt8+7sLHIvc+24KOsz8i+2bj2wPXX06Osx9DJ7czlu+HSu8/Co6E8L3A+DQo8cD48c3Ryb25nPjEu0Ke5+828PC9zdHJvbmc+PC9wPg0KPHA+PGltZyBhbHQ9"ValueAnimator" src="/uploadfile/Collfiles/20160912/20160912092704460.gif" title="\" />

2.具體代碼

ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f);
valueAnimator.setDuration(3000);
//設置監聽,把當前AnimatedValue的值時時顯示到EditText上面
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float currentValue = (float) animation.getAnimatedValue();
        StringBuilder sb = new StringBuilder();
        et_Animator.setText(sb.append(currentValue).toString());
    }
});
valueAnimator.start();

ValueAnimator比較常用的方法有:設置AnimatorValue區間范圍的三個主要方法
ofFloat(),ofInt(),ofObject()
還有設置延時播放時間的setStartDelay()方法,設置重復次數的setRepeatCount()方法,設置重復模式的setRepeatMode()
暫停動畫的pause()方法,恢復動畫的resume()等等,還有很多方法,具體大家可以查閱文檔,把這個核心類的方法掌握了,使用ObjectAnimator就能更加得心應手,因為從繼承關系中我們可以知道ObjectAnimator是ValueAnimator的子類。

ObjectAnimator

ObjectAnimator對象應該是我們產生屬性動畫效果最常用的類了,ValueAnimator僅僅是對數值進行平滑的過渡變化,而如果我們想對一個對象的任意屬性進行動畫效果,就需要使用ObjectAnimator對象了,還是先舉個簡單栗子吧。

1.效果圖

Alpha動畫

2.具體代碼

//ofFloat(需要實現動畫的控件ID,需要實現的動畫效果名稱,變化的區間范圍)
ObjectAnimator objAnim = bjectAnimator.ofFloat(et_Animator,"alpha",0f, 1f, 0f, 1f);
objAnim.setDuration(6000);
objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float currentValue = (float) animation.getAnimatedValue();
        StringBuilder sb = new StringBuilder();
        et_Animator.setText(sb.append(currentValue).toString());
    }
});
objAnim.start();

以上代碼實現的效果是:在6000毫秒內,讓EditText控件平滑的實現了從完全透明>完全不透明>完全透明>完全不透明的過渡效果;並且對整個動畫執行過程設置了監聽,時時把當前動畫的AnimatorValue值顯示到EditText控件上面。

根據設置參數的不同,使用ObjectAnimator對象還可以實現translationX(豎直平移),translationY(水平平移),rotation(旋轉),scaleX(水平縮放),scaleY(豎直縮放)等其他效果。當然還可以使用AnimatorSet對象來產生組合動畫效果。

效果圖

綜合栗子

具體代碼
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn_OperationAnimator;
    private EditText et_Animator;
    private RadioGroup radioGroup;
    private ObjectAnimator objAnim;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et_Animator = (EditText) findViewById(R.id.et_Animator);
        radioGroup = (RadioGroup) findViewById(R.id.radioGroup);
        btn_OperationAnimator = (Button) findViewById(R.id.btn_OperationAnimator);

        btn_OperationAnimator.setOnClickListener(this);

    }
    @Override
    public void onClick(View v) {

        int checkedId = radioGroup.getCheckedRadioButtonId();

        switch (checkedId) {

            case R.id.rb_value:
                ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f);
                valueAnimator.setDuration(3000);
                valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        float currentValue = (float) animation.getAnimatedValue();
                        StringBuilder sb = new StringBuilder();
                        et_Animator.setText(sb.append(currentValue).toString());
                    }
                });
                valueAnimator.start();
                break;

            case R.id.rb_alpha:
                objAnim = ObjectAnimator.ofFloat(et_Animator,"alpha",0f, 1f, 0f, 1f);
                objAnim.setDuration(3000);
                objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        float currentValue = (float) animation.getAnimatedValue();
                        StringBuilder sb = new StringBuilder();
                        et_Animator.setText(sb.append(currentValue).toString());
                    }
                });
                objAnim.start();
                break;
            case R.id.rb_translationX:
                objAnim = ObjectAnimator.ofFloat(et_Animator,"translationX",0f, 100f, 0f, 200f, 0f);
                objAnim.setDuration(3000);
                objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        float currentValue = (float) animation.getAnimatedValue();
                        StringBuilder sb = new StringBuilder();
                        et_Animator.setText(sb.append(currentValue).toString());
                    }
                });
                objAnim.start();
                break;
            case R.id.rb_translationY:
                objAnim = ObjectAnimator.ofFloat(et_Animator,"translationY",0f, 100f, 0f, 200f, 0f);
                objAnim.setDuration(3000);
                objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        float currentValue = (float) animation.getAnimatedValue();
                        StringBuilder sb = new StringBuilder();
                        et_Animator.setText(sb.append(currentValue).toString());
                    }
                });
                objAnim.start();
                break;
            case R.id.rb_rotation:
                objAnim = ObjectAnimator.ofFloat(et_Animator,"rotation",0f, 180f, 0f, 360f, 0f);
                objAnim.setDuration(6000);
                objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        float currentValue = (float) animation.getAnimatedValue();
                        StringBuilder sb = new StringBuilder();
                        et_Animator.setText(sb.append(currentValue).toString());
                    }
                });
                objAnim.start();
                break;
            case R.id.rb_scaleX:
                objAnim = ObjectAnimator.ofFloat(et_Animator,"scaleX", 4f, 1f, 2f, 1f);
                objAnim.setDuration(3000);
                objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        float currentValue = (float) animation.getAnimatedValue();
                        StringBuilder sb = new StringBuilder();
                        et_Animator.setText(sb.append(currentValue).toString());
                    }
                });
                objAnim.start();
                break;
            case R.id.rb_scaleY:
                objAnim = ObjectAnimator.ofFloat(et_Animator,"scaleY",1f, 5f, 2f, 1f);
                objAnim.setDuration(3000);
                objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        float currentValue = (float) animation.getAnimatedValue();
                        StringBuilder sb = new StringBuilder();
                        et_Animator.setText(sb.append(currentValue).toString());
                    }
                });
                objAnim.start();
                break;
            case R.id.rb_animatorSet:
                ObjectAnimator objAnim_alpha = ObjectAnimator.ofFloat(et_Animator,"alpha",0f, 1f, 0f, 1f);
                ObjectAnimator objAnim_translationX = ObjectAnimator.ofFloat(et_Animator,"translationX",0f, 100f, 0f, 200f, 0f);
                ObjectAnimator objAnim_translationY = ObjectAnimator.ofFloat(et_Animator,"translationY",0f, 100f, 0f, 200f, 0f);
                ObjectAnimator objAnim_rotation = ObjectAnimator.ofFloat(et_Animator,"rotation",0f, 180f, 0f, 360f, 0f);
                ObjectAnimator objAnim_scaleX = ObjectAnimator.ofFloat(et_Animator,"scaleX", 4f, 1f, 2f, 1f);
                ObjectAnimator objAnim_scaleY = ObjectAnimator.ofFloat(et_Animator,"scaleY",1f, 5f, 2f, 1f);
                AnimatorSet animSet = new AnimatorSet();
                animSet.play(objAnim_alpha)
                        .before(objAnim_rotation)    //在play動畫之後執行
                        .after(objAnim_scaleX)       //在play動畫之前執行
                        .after(objAnim_scaleY)
                        .with(objAnim_translationX)  //和play動畫同時執行
                        .with(objAnim_translationY);
                animSet.setDuration(5000);
                animSet.start();
                break;
        }
    }
}

栗子很簡單,算是做個自我鞏固以及方便日後回顧,如果不小心幫到別人了那自然也是極好的。

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