Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android5.0:全新的動畫(animation)

android5.0:全新的動畫(animation)

編輯:關於Android編程

全新的動畫

在Material Design設計中,為用戶與app交互反饋他們的動作行為和提供了視覺上的連貫性。Material主題為控件和Activity的過渡提供了一些默認的動畫,在android L上,允許自定義這些動畫:

  1. Touch feedback 觸摸反饋
  2. Circular Reveal 圓形展示
  3. Curved motion 曲線運動
  4. View state changes 視圖狀態變化
  5. Vector Drawables 矢量圖動畫
  6. Activity transitions 活動轉場

觸摸反饋

觸摸反饋是指用戶在觸摸控件時的一種可視化交互,在Android L之前,通常是通過press色變來凸顯,但是因為是瞬間變化的效果,不如動畫生動。

在Android L使用了RippleDrawable類,用一個水波紋擴散效果在兩種不同的狀態間過渡。

使用Material Design樣式的應用,button默認帶有該效果。除了默認的效果外,系統還提供了另外兩種效果,我們只把button的背景指定為:

  1. ?android:attr/selectableItemBackground
  2. ?android:attr/selectableItemBackgroundBorderless

    任何view處於可點擊狀態,都可以使用RippleDrawable來達到水波紋特效。

    我們也可以通過設置RippleDrawable的顏色屬性來調節動畫顏色,系統默認的顏色為主題的一個屬性顏色:android:colorControlHighlight,所以我們可以通過修改該顏色值來統一修改默認的水波紋顏色。android:colorAccent可以修改checkbox的選中顏色,更多顏色設置請參考主題。

    系統的三種觸摸反饋都是通過xml構建的,內容如下:

    默認:
    
        
            
                
                    
                    
                    
                
            
        
    
    
    
    ?android:attr/selectableItemBackground
    
        
            
        
    
    
    ?android:attr/selectableItemBackgroundBorderless
    

 



代碼中設置
RippleDrawableColorStateList stateList = getResources().getColorStateList(R.color.tint_state_color);
RippleDrawable rippleDrawable = new RippleDrawable(stateList,null,null);
view.setBackground(rippleDrawable);

圓形展示

我們通常會顯示或者隱藏一個view,在Android L之前,這是一個生硬瞬間變化動作,現在,有了一個新的api為此效果提供一個圓形的顯示或者隱藏的動畫效果。

RevealAnimator和之前的動畫使用沒什麼區別,同樣可以設置監聽器和加速器來實現各種各樣的特效,該動畫主要用在隱藏或者顯示一個view,改變view的大小等過渡效果。

通過ViewAnimationUtils.createCircularReveal來創建一個動畫,該api接受5個參數:

  1. view 操作的視圖
  2. centerX 動畫開始的中心點X
  3. centerY 動畫開始的中心點Y
  4. startRadius 動畫開始半徑
  5. startRadius 動畫結束半徑

沿著中心的縮小的動畫

Animator animator = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2, view.getHeight() / 2, view.getWidth(), 0);
animator.setInterpolator(new LinearInterpolator());
animator.setDuration(1000);
animator.start();

從左上角擴展的圓形動畫

Animator animator = ViewAnimationUtils.createCircularReveal(view,0,0,0,(float) Math.hypot(view.getWidth(), view.getHeight()));
animator.setDuration(1000);
animator.start();

曲線運動

曲線動畫在Android L之前我們可以通過繼承位移動畫重載applyTransformation函數來實現運動軌跡算法,但是操作起來比較繁瑣:

通過繼承位移動畫,來改寫applyTransformation來修改位移的軌跡

通過繼承位移動畫,來改寫applyTransformation來修改位移的軌跡

public class ArcTranslateAnimation extends Animation {
    private float mFromXValue,mToXValue,mFromYValue,mToYValue;
    private float mFromXDelta,mToXDelta,mFromYDelta,mToYDelta;
    private PointF mStart,mControl,mEnd;
    public ArcTranslateAnimation(float fromXValue, float toXValue, float fromYValue, float toYValue) {
        mFromXValue = fromXValue;
        mToXValue = toXValue;
        mFromYValue = fromYValue;
        mToYValue = toYValue;
    }
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        float dx = calcBezier(interpolatedTime, mStart.x, mControl.x, mEnd.x);
        float dy = calcBezier(interpolatedTime, mStart.y, mControl.y, mEnd.y);
        t.getMatrix().setTranslate(dx, dy);
    }
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        mFromXDelta = resolveSize(ABSOLUTE, mFromXValue, width, parentWidth);
        mToXDelta = resolveSize(ABSOLUTE, mToXValue, width, parentWidth);
        mFromYDelta = resolveSize(ABSOLUTE, mFromYValue, height, parentHeight);
        mToYDelta = resolveSize(ABSOLUTE, mToYValue, height, parentHeight);
        mStart = new PointF(mFromXDelta, mFromYDelta);
        mEnd = new PointF(mToXDelta, mToYDelta);
        mControl = new PointF(mFromXDelta, mToYDelta);
    }
    private long calcBezier(float interpolatedTime, float p0, float p1, float p2) {
        return Math.round((Math.pow((1 - interpolatedTime), 2) * p0) 
        + (2 * (1 - interpolatedTime) * interpolatedTime * p1) + 
        (Math.pow(interpolatedTime, 2) * p2);
    }
}

 

現在我們有了更簡單的實現方式。

ObjectAnimator新增了path方式來構建動畫,並且可以同時對x,y兩個屬性做動畫,我們只用指定一個曲線的path,即可作出曲線的動畫,可以用quadTo/cubicTo繪制貝塞爾曲線,也可以使用arcTo繪制普通的弧線 新增了PathInterpolator動畫插入器,新的基於貝塞爾曲線或路徑對象的插入器。這個插入器指定了一個1x1正方形運動曲線,它使用(0,0)為錨點,(1,1)為控制點,作為構造函數的參數。

Path path = new Path();
path.moveTo(100,100);
path.quadTo(1000,300,300,700);
ObjectAnimator mAnimator = ObjectAnimator.ofFloat(curved, View.X, View.Y, path);
Path p = new Path();
p.lineTo(0.6f, 0.9f);
p.lineTo(0.75f, 0.2f);
p.lineTo(1f, 1f);
mAnimator.setInterpolator(new PathInterpolator(p));
mAnimator.setDuration(3000);
mAnimator.start();

視圖狀態變化

Android L在原有的圖片選擇器和顏色選擇器上進行了增強,不僅是控件能根據不同的狀態顯示不同的背景圖片,還能在兩種狀態切換時指定一個動畫,來增加過渡效果,吸引用戶眼球,以突出重點內容。

StateListAnimator類和圖片選擇器,顏色選擇器類似,可以根據view的狀態改變呈現不同的動畫效果,通過xml我們可以構建對應不同狀態的動畫合集,其使用方式也非常簡單,在對應的狀態指定一個屬性動畫即可:


    
        
            
    
    
        
            
    

 

在xml中通過android:stateListAnimator來指定狀態動畫,代碼中可以通過AnimationInflater.loadStateListAnimator()加載動畫,並使用View.setStateListAnimator()將其指定給View。

可以在狀態切換的過程指定多個屬性動畫的合集,繼承了Material主題後,按鈕默認擁有了z屬性動畫。如果想取消這種默認狀態,可以把狀態動畫指定為null。

除了StateListAnimator類指定狀態切換的屬性動畫外,還可以通過AnimatedStateListDrawable來指定狀態切換的幀動畫:


    
    
    
        
            
            
            
        
    

 

矢量圖動畫

前面我們學習了矢量圖,AnimatedVectorDrawable類讓你能使一個矢量圖動起來。矢量圖動畫比幀動畫更平滑的展現圖片的變化過程,並且無論在內存占用,還是包體積占用上都要優於幀動畫。通常定義一個矢量圖動畫需要三步:

在drawable資源目錄下定義一個矢量圖


    
        
    

 

在anim下頂一個objectAnimator,並在動畫中修改矢量圖的path


    

 

在drawable下定義一個animated-vector,並把drawable指向矢量圖,把target中的動畫指定為之前定義的objectAnimator


    

 

轉場動畫

在Android L之前,我們可以在startActivity之後調用overridePendingTransition來指定Activity的轉場動畫。現在Android L給我們帶來了更絢麗的轉場動畫。

新的轉場動畫分為兩大類,一種是普通的過渡動畫,另一種是共享元素的過渡動畫。 要想使用新的轉場動畫,可以繼承Material Design主題後在style風格中指定:

 

也可以在activity的oncreate方法中進行代碼設置:

// 允許使用transitions
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
// 指定進入、退出、返回、重新進入時的transitions
getWindow().setEnterTransition(new Explode());
getWindow().setExitTransition(new Explode());
getWindow().setEnterTransition(new Explode());
getWindow().setExitTransition(new Explode());
// 指定進入、退出、返回、重新進入時的共享transitions
getWindow().setSharedElementEnterTransition(new ChangeTransform());
getWindow().setSharedElementExitTransition(new ChangeTransform());
getWindow().setSharedElementReturnTransition(new ChangeTransform());
getWindow().setSharedElementReenterTransition(new ChangeTransform());
普通轉場動畫

所有繼承自visibility類都可以作為進入、退出的過度動畫。如果我們想自定義進入和退出時的動畫效果,只需要繼承Visibility,重載onAppear和onDisappear方法來定義進入喝退出的動畫。系統提供了三種默認方式:

  1. explode 從屏幕中心移入或移出視圖
  2. slide 從屏幕邊緣移入或移出視圖
  3. fade 改變視圖的透明度

想在xml中指定自定義的進入、退出的過度動畫需要先對動畫進行定義:


 

注意:其中CustomTransition是你自定義的動畫,它必須繼承自Visibility。

想以普通轉場動畫的方式啟動一個Activity,必須在startActivity函數中傳遞一個ActivityOptions的Bundle對象:

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(activity);  
startActivity(intent, options.toBundle());  

如果想讓返回也具備轉場效果,那麼在返回的Activity中不要再調用finish函數,而是應該使用finishAfterTransition來結束一個Activity,該函數會等待動畫執行完畢才結束該Activity。

共享轉場動畫

當兩個Activity具備某些相遇的元素時,共享轉場動畫將是一個非常好的選擇。使用轉場動畫需要將相同的元素通過android:transitionName或者view.setTransitionName設置為相同的名稱,這樣系統才能區分出相同的元素。

共享轉場動畫支持以下共享元素:

  1. changeBounds 對目標視圖的大小進行動畫
  2. changeClipBounds 對目標視圖的剪裁大小進行動畫
  3. changeTransform 對目標視圖進行縮放、旋轉、位移動畫
  4. changeImageTransform 對目標圖片進行縮放

通過下面的函數啟動一個共享元素動畫:

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(activity, view, "name");  
startActivity(intent, options.toBundle()); 

如果有多個共享元素,則可以通過Pair進行包裝處理:

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(activity,Pair.create(view1, "name1"),Pair.create(view2, "name2"));      
startActivity(intent,.toBundle());

返回時如果需要具備轉場動畫,那麼也需要用finish函數替代finishAfterTransition來結束一個Activity。

共享轉場動畫通常可以根據指定的元素判斷出合適的轉場動畫效果,不需要我們做額外的處理,也可以通過之前學習的方法進行指定共享元素轉場動畫效果。

組合轉場動畫

我們可以把多個轉場動畫進行組合,作出更具個性的轉場效果,在資源文件中通過以下方式:


    
    
    < 

 

代碼中我們可以通過TransitionSet類組合多個轉場動畫:

TransitionSet transitionSet = new TransitionSet();
transitionSet.addTransition(new Fade());
transitionSet.addTransition(new ChangeBounds());

組合可以同時針對普通轉場動畫和共享元素轉場動畫。

轉場動畫也可以像普通動畫一樣設置持續時間,延期執行時間,速率插入器,以及動畫的監聽等。

轉場動畫通常是對整個布局起作用,如果我們想對某個特定的view實施轉場動畫,可以把該view設置為轉場動畫的target,這樣轉場動畫將只對特定的view起作用。共享元素的動畫的target需要指定為transitionName

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