Android動畫

前言

在Android開發中,UI的變化很是常見,若是不使用動畫來進行過分,那麼用戶體驗就會不怎麼好。我將動畫分爲大三類View動畫、幀動畫、屬性動畫三種,下面先從View動畫開始java

1、View動畫

View動畫包括如下幾種android

  • ScaleAnimation(縮放動畫)
  • TranslateAnimation(平移動畫)
  • AlphaAnimation(透明度動畫)
  • RotateAnimation(旋轉動畫)

而且還提供了一個AnimationSet類來把多個View動畫進行組合顯示,咱們能夠直接在代碼中建立這些Animation對象也能夠在xml中進行指定bash

縮放動畫ide

  • 代碼中定義
ScaleAnimation sAnimation = new ScaleAnimation(0, 1, 0,
                1, Animation.RELATIVE_TO_SELF, 0.5f, 
                Animation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(2000);
imageView.startAnimation(sAnimation);
複製代碼
  • xml中定義
<scale xmlns:android="http://schemas.android.com/apk/res/android" android:fromXScale="0" android:toXScale="1" android:fromYScale="0" android:toYScale="1" android:pivotX="50%" android:pivotY="50%" android:duration="2000">
</scale>
複製代碼

平移動畫post

  • 代碼中定義
TranslateAnimation tAnimation = new TranslateAnimation(0, 100, 0, 100);
tAnimation.setDuration(2000);
imageView.startAnimation(tAnimation);
複製代碼
  • xml中定義
<translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fromXDelta="0" android:toXDelta="200" android:fromYDelta="0" android:toYDelta="200">
</translate>
imageView.startAnimation(AnimationUtils.loadAnimation(this, R.anim.translate));
複製代碼

透明度動畫動畫

  • 代碼中定義
AlphaAnimation aAnimation = new AlphaAnimation(0, 1);
aAnimation.setDuration(2000);
imageView.startAnimation(aAnimation);
複製代碼
  • xml中定義
<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fromAlpha="0" android:toAlpha="1">
</alpha>
複製代碼

旋轉動畫this

  • 代碼中定義
RotateAnimation rAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
rAnimation.setDuration(2000);
imageView.startAnimation(rAnimation);
複製代碼
  • xml中定義
<rotate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fromDegrees="0" android:toDegrees="360">
</rotate>
複製代碼

組合動畫spa

  • 代碼中定義
AnimationSet set = new AnimationSet(true);
set.addAnimation(sAnimation);
set.addAnimation(aAnimation);
set.addAnimation(tAnimation);
set.addAnimation(rAnimation);
// 全部子動畫都會被設置成該超時時間
set.setDuration(5000);
imageView.startAnimation(set);
複製代碼
  • xml中定義
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <alpha android:duration="2000" android:fromAlpha="0" android:toAlpha="1">
    </alpha>
    <rotate android:duration="2000" android:fromDegrees="0" android:toDegrees="360">
    </rotate>
    <scale android:fromXScale="0" android:toXScale="1" android:fromYScale="0" android:toYScale="1" android:pivotX="50%" android:pivotY="50%" android:duration="2000">
    </scale>
    <translate android:duration="2000" android:fromXDelta="0" android:toXDelta="200" android:fromYDelta="0" android:toYDelta="200">
    </translate>
</set>
複製代碼

以上代碼有幾個須要注意3d

  • 在xml中定義的動畫能夠經過AnimationUtils.loadAnimation(context, resId))拿到對應的Animation對象
  • 若是想讓一個動畫延時執行能夠設置startOffset
  • 若是想讓一個動畫循環執行能夠設置repeatCount
  • 動畫執行完後默認會返回到原始位置若是不須要返回那麼須要將setFillAfter設置爲true,可是雖然執行完後保留在了執行完後的位置可是該位置並不能響應點擊事件,原位置可以響應點擊事件
  • 上述動畫都沒有設置插值器,採用默認的插值器AccelerateDecelerateInterpolator,若是想要動畫按照不停的速率運行,那麼能夠設置如下幾種插值器
插值器類 對應xml資源id 變化方式
AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 先加速後減速
AccelerateInterpolator @android:anim/accelerate_interpolator 一直加速
AnticipateInterpolator @android:anim/anticipate_interpolator 先往反方向運動一段距離再前進
AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 先往反方向運動再前進而且超過目標點,最後回到目標點
BounceInterpolator @android:anim/bounce_interpolator 相似球落地時的反彈效果
CycleInterpolator @android:anim/cycle_interpolatorr 循環,先往正向運動到終點,而後向反方向運動知道運動到-終點處再回來
DecelerateInterpolator @android:anim/decelerate_interpolator 一直減速
LinearInterpolator @android:anim/linear_interpolator 勻速運動
OvershootInterpolator @android:anim/overshoot_interpolator 移動超過目標點,而後再回來

LayoutAnimation

若是一個ViewGroup被設置了該屬性那麼在第一次顯示該ViewGroup時會執行所設置的動畫,用法以下。code

首先定義一個AnimationSet

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <alpha android:duration="2000" android:fromAlpha="0" android:toAlpha="1">
    </alpha>
    <translate android:duration="2000" android:fromYDelta="100%p" android:toYDelta="0">
    </translate>
</set>
複製代碼

而後再res/anim裏面創建一個根節點爲layoutAnimation文件,引用上述的文件,其中的delay表示對應ViewGroup中的每一個View都要延遲動畫duration * delay的時間,如今動畫持續時間是2000ms,那麼第一個item就會在600ms的時候執行動畫,第二個會在1200ms的時候執行

<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:animationOrder="normal" android:animation="@anim/set" android:delay="0.3">
</layoutAnimation>
複製代碼

最後給目標ViewGroup設置LayoutAnimation

<android.support.v7.widget.RecyclerView android:id="@+id/rv" android:background="@color/colorPrimary" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layoutAnimation="@anim/layout_animation" android:orientation="vertical">

</android.support.v7.widget.RecyclerView>
複製代碼

運行效果以下圖所示,固然有點醜,須要的時候能夠慢慢調整

2、幀動畫

幀動畫就是將一組圖片按照特定的順序進行播放, 使用方式以下所示

<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true">
    <item android:drawable="@drawable/s1" android:duration="1000"/>
    <item android:drawable="@drawable/s2" android:duration="1000"/>
    <item android:drawable="@drawable/s3" android:duration="1000"/>
    <item android:drawable="@drawable/s4" android:duration="1000"/>
    <item android:drawable="@drawable/s5" android:duration="1000"/>
    <item android:drawable="@drawable/s6" android:duration="5000"/>
    <item android:drawable="@drawable/s7" android:duration="1000"/>
</animation-list>

imageView.setImageResource(R.drawable.list);
mDrawable = (AnimationDrawable)imageView.getDrawable();
imageView.post(new Runnable() {
    @Override
    public void run() {
        mDrawable.start();
    }
});
複製代碼

這裏有幾個注意點

  • oneshot表示是否只播放一次,該值默認是false表示循環播放
  • 幀動畫在View三大流程執行完畢前,只會顯示第一幀因此要在三大流程執行完成後再開啓

3、屬性動畫

前面講到的View動畫其實並不會真正改變View的屬性好比位置等等,而屬性動畫會真正的改變View的屬性,其主要類包括如下幾個,其中ObjectAnimator繼承於ValueAnimator,先來看看ViewPropertyAnimator

  • ViewPropertyAnimator
  • ValueAnimator
  • ObjectAnimator
  • AnimatorSet

ViewPropertyAnimator

這個類內部實際上是經過ValueAnimator實現的,咱們能夠經過view.animator()獲得該類的對象

// translation從當前值慢慢的變爲100
imageView.animate().translationX(100);
// translation從當前值慢慢的變爲原來值+100
imageView.animate().translationXBy(100);
// 反轉180度
imageView.animate().rotation(180);
複製代碼

注意咱們不須要手動調用start方法其就會自動運行,默認持續時間是300ms

ValueAnimator

咱們能夠經過ofInt、ofFloat、ofArgb等獲取到ValueAnimator實例,下面以經過屬性動畫動態改變圖片的高度爲例

在代碼中定義

ValueAnimator vAnimator = ValueAnimator.ofInt(400, 0);
vAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        ViewGroup.LayoutParams params = imageView.getLayoutParams();
        params.height = (int) animation.getAnimatedValue();
        imageView.setLayoutParams(params);
    }
});
vAnimator.setDuration(3000);
vAnimator.start();
複製代碼

在xml中定義

<animator xmlns:android="http://schemas.android.com/apk/res/android" android:valueFrom="400dp" android:valueType="intType" android:valueTo="0dp" android:duration="3000">
</animator>
ValueAnimator vAnimator =
                (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator);
複製代碼

ObjectAnimator

咱們能夠經過ofInt、ofFloat、ofArgb等獲取到ObjectAnimator實例,通常會操做如下幾個屬性

  • translationX、translationY 平移
  • rotation、rotationX、rotationY 旋轉
  • privotX、privotY 控制旋轉縮放的支點位置
  • alpha 透明度
  • x 、y 、z位置

下面以經過屬性動畫動態改變圖片的透明度爲例

在代碼中定義

ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 0, 1);
animator.setDuration(3000);
animator.start();
複製代碼

在xml中定義

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:valueType="floatType" android:duration="3000" android:propertyName="alpha" android:valueFrom="0" android:valueTo="1">
</objectAnimator>
ObjectAnimator animator = (ObjectAnimator)
                AnimatorInflater.loadAnimator(this, R.animator.object_animator);
animator.setTarget(imageView);
animator.start();
複製代碼

幾個注意點:

  • 當ofXXX屬性名參數後面只有一個參數時那個參數表示的是目標值,系統會調用getter獲取初始化值,而後不停的調用setter設置,當超過一個參數時第一個就變爲初始值最後一個變成目標值,中間的都是轉接點這個時候能夠不提供setter方法
  • 當一個類的某個屬性沒有提供setter方法時咱們須要對其運用屬性動畫,咱們能夠建一個包裝類
  • 若是發現使用了屬性動畫改變自定義View的屬性發現界面並無發生變化,請檢查下你的setter方法有沒有觸發重繪

AnimatorSet

AnimatorSet相似AnimationSet,做用是把多個屬性動畫組合起來執行

在代碼中定義

ValueAnimator vAnimator =
                (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator);
vAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        ViewGroup.LayoutParams params = imageView.getLayoutParams();
        params.height = (int) animation.getAnimatedValue();
        imageView.setLayoutParams(params);
    }
});
vAnimator.setDuration(3000);
vAnimator.start();
ObjectAnimator oAnimator = (ObjectAnimator)
        AnimatorInflater.loadAnimator(this, R.animator.object_animator);
oAnimator.setTarget(imageView);
oAnimator.start();
AnimatorSet set = new AnimatorSet();
// 同時執行
set.playTogether(vAnimator, oAnimator);
// 順序執行
set.playSequentially(vAnimator, oAnimator);
複製代碼

在xml中定義 其中ordering表示同時執行仍是順序執行

<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together">
    <animator android:valueFrom="400px" android:valueTo="0px" android:duration="3000" android:valueType="intType">
    </animator>
    <objectAnimator android:valueType="floatType" android:duration="3000" android:propertyName="alpha" android:valueFrom="0" android:valueTo="1">
    </objectAnimator>
</set>
複製代碼

PropertyValuesHolder

使用PropertyValuesHolder也能實現多動畫同時執行

PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("alpha", 0, 1);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofInt("rotation", 0, 360);
ValueAnimator animator = ObjectAnimator.ofPropertyValuesHolder(holder1, holder2);
animator.setDuration(3000);
animator.setTarget(imageView);
animator.start();
複製代碼

Tips: 將ViewGroup的animateLayoutChanges屬性設置爲true,在添加View或者移除View的時候會有動畫

相關文章
相關標籤/搜索