1. 程式人生 > >Android過渡動畫(Transition Animation)

Android過渡動畫(Transition Animation)

本篇部落格記錄一下Android中過渡動畫的用法。
過渡動畫是Android 4.4引入的新的動畫框架,它本質上仍是屬性動畫,
但對屬性動畫做了一層封裝,以方便開發者實現Activity或者View的過渡動畫效果。

和屬性動畫相比,過渡動畫最大的不同是需要為動畫前後準備不同的佈局,
並通過對應的API實現兩個佈局的之間過渡動畫。

不過相對而言,過渡動畫比較吃記憶體,據傳聞傳聞,
在針對低記憶體裝置的Android Go版本中,部分過渡動畫會被砍掉。

一、簡單示例
我們先來看看Transition動畫的簡單使用示例。

如下圖所示,我們的Activity中定義了3個ImageView。
現在,我們準備將這些試圖順時針旋轉一下。


如果使用補間動畫或屬性動畫,為了實現這個需求,
我們需要寫3個位置移動動畫,然後分別應用到這三個View上面。
若使用過渡動畫,整個實現過程則會簡單的多。

準備工作
我們首先定義一下Activity對應的佈局檔案:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
android:orientation="vertical">
<Button android:id="@+id/begin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="開始動畫"/> <!--做動畫的父佈局--> <FrameLayout android:id="@+id/rootView" android:layout_width
="match_parent" android:layout_height="wrap_content">
<!--scene1為動畫的初始佈局--> <include layout="@layout/scene1"/> </FrameLayout> </LinearLayout>

定義啟始與結束幀
在layout目錄下定義初始時的檢視佈局檔案scene1.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/image1"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/p_1"
        android:layout_centerInParent="true"/>

    <ImageView
        android:id="@+id/image2"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/p_2"
        android:layout_below="@id/image1"
        android:layout_alignParentLeft="true"/>

    <ImageView
        android:id="@+id/image3"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/p_3"
        android:layout_below="@id/image1"
        android:layout_alignParentRight="true"/>

</RelativeLayout>

然後,我們還需要定義結束時的檢視佈局檔案scene2.xml,
注意檢視中View的id與scene1.xml中一一對應:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/image3"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/p_3"
        android:layout_centerInParent="true"/>

    <ImageView
        android:id="@+id/image1"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/p_1"
        android:layout_below="@id/image3"
        android:layout_alignParentLeft="true"/>

    <ImageView
        android:id="@+id/image2"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/p_2"
        android:layout_below="@id/image3"
        android:layout_alignParentRight="true"/>

</RelativeLayout>

定義過渡效果
在過渡動畫框架中,過渡效果均是繼承Transition類。
框架內建了一些常用的效果,比如幻燈片Slide,淡入淡出 Fade等。
由於我們這裡3個View涉及的都是位置的變化,
我們可以直接使用框架內建的動畫效果ChangeBounds(實際上是變換檢視邊界的座標)。

實際的使用

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ViewGroup rootView = findViewById(R.id.rootView);

        Button button = findViewById(R.id.begin);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    //定義結束Scene
                    Scene scene2 = Scene.getSceneForLayout(rootView, R.layout.scene2, MainActivity.this);

                    //利用TransitionManager進行變換
                    TransitionManager.go(scene2, new ChangeBounds());
                }
            }
        });
    }
}

至此,我們已經可以看出過渡動畫的基本使用方式。

如上面的示意圖所示:
首先,利用佈局檔案定義了一個檢視樹的兩種狀態(類似於開始幀和結束幀),這些狀態被稱為Scene。
Scene定義了頁面的當前狀態資訊,Scene的例項化一般通過靜態工廠方法實現:

public static Scene getSceneForLayout(ViewGroup sceneRoot, int layoutId, Context context) {
    .............
}

然後,選定需要使用的動畫效果,例如ChangeBounds等,
它能夠處理View本身大小、位置改變,描述這些變化效果的物件就被成為Transition。
Transition定義了介面之間切換的動畫資訊,在使用TransitionManager時,
如果沒有指定使用哪個Transition,那麼會使用預設的AutoTransition。
AutoTranstion的效果就是先隱藏,後移動,最後顯示:

public class AutoTransition extends TransitionSet {
    ...........
    private void init() {
        setOrdering(ORDERING_SEQUENTIAL);
        addTransition(new Fade(Fade.OUT)).
                addTransition(new ChangeBounds()).
                addTransition(new Fade(Fade.IN));
    }
}

最後,通過TransitionManager的介面,開啟整個檢視的動畫轉換即可。
TransitionManager就是控制Scene之間切換的控制器。

二、場景Scene
從前文的程式碼我們知道,Scene記錄了一個檢視樹中所有View的屬性值。
前面我們使用如下介面構造Scene:

public static Scene getSceneForLayout(ViewGroup sceneRoot, int layoutId, Context context) {
    .............
}

除此之外,我們也可以利用建構函式直接建立Scene:

public Scene(ViewGroup sceneRoot, View layout) {
    ......
}

可以看到,無論使用哪種方式建立Scene,都必須指定sceneRoot。
sceneRoot就是Scene對應檢視樹的根View。

當過渡動畫開始時,sceneRoot中與初始Scene有關的View都會被remove,
即初始Scene中的View必須都是sceneRoot的子View;
在動畫的結束時,sceneRoot重新新增結束Scene相關的View,
即結束Scene中的View必須都是sceneRoot的子View,或沒有ParentView的View,
否則addView時會報錯。

三、過渡Transition
Transition針對初始和結束場景對應檢視樹中View的屬性,
例如width、height、position等,定義了變化時的過度效果。
Android目前內建了ChangeBounds、Fade等。

3.1、指定目標
前面示例中,Transition直接作用在整個檢視樹,
即對檢視樹上所有的View均生效。

如果不想將動畫效果應用到所有的View上,
可以利用Transition的addTarget或removeTarget指定生效的View。
例如前面的例子,可以修改為:

.................
Scene scene2 = Scene.getSceneForLayout(rootView,
        R.layout.scene2, MainActivity.this);
Transition transition = new ChangeBounds();
transition.addTarget(R.id.image1);
TransitionManager.go(scene2, transition);
.................

此時,只有image1對應檢視在變化時有動畫效果。

3.2、延遲動畫
之前已經提到過,過渡動畫實際上也是一種屬性動畫。
這一點從TransitionManager提供的延遲動畫介面就可以看出來。
使用延遲動畫介面時,不需要定義結束幀對應的Scene。
仍然使用前文的示例程式碼:

ChangeBounds changeBounds = new ChangeBounds();
changeBounds.setDuration(3000);
//開啟延遲動畫
TransitionManager.beginDelayedTransition(rootView, changeBounds);

//可以直接修改rootView中子View的屬性
//當動畫結束後,子View的屬性就會被修改到指定值

View image1 = findViewById(R.id.image1);
ViewGroup.LayoutParams params1 = image1.getLayoutParams();
params1.height = 200;
params1.width = 200;
image1.setLayoutParams(params1);

View image2 = findViewById(R.id.image2);
ViewGroup.LayoutParams params2 = image2.getLayoutParams();
params2.height = 400;
params2.width = 400;
image2.setLayoutParams(params2);

當TransitionManager呼叫beginDelayedTransition後,系統會儲存當前檢視樹的狀態;
接著在程式碼中,我們修改了子View的屬性;
在下一次繪製時,系統會比對檢視樹當前的狀態和之前儲存的狀態,
然後系統就會執行過渡動畫,並按照新的狀態繪製View。

3.3、自定義Transition
這部分我們來看看如何自定義Transition,直接上例子:

    //我定義了一個起始和結束時,View的高度發生變化時,就會旋轉的動畫效果
    @TargetApi(19)
    private class RotateWhenHeightChangeTransition extends Transition {
        private static final String PROP_NAME_TRANSITION_HEIGHT = "zhang:jian:just:for:test";

        //首先必須複寫captureStartValues和captureEndValues
        //如同函式名,這裡主要記錄我們感興趣的資料
        //按照鍵值對的形式存入transitionValues.values

        //記錄開始Scene中View的高度
        @Override
        public void captureStartValues(TransitionValues transitionValues) {
            transitionValues.values.put(
                    PROP_NAME_TRANSITION_HEIGHT, transitionValues.view.getLayoutParams().height);
        }

        //記錄結束Scene中View的高度
        @Override
        public void captureEndValues(TransitionValues transitionValues) {
            transitionValues.values.put(
                    PROP_NAME_TRANSITION_HEIGHT, transitionValues.view.getLayoutParams().height);
        }

        @Override
        public Animator createAnimator(ViewGroup sceneRoot,
                                       TransitionValues startValues, TransitionValues endValues) {
            if (startValues == null || endValues == null) {
                return null;
            }

            //比對開始和結束時,高度是否發生變化
            int startHeight = (int)startValues.values.get(PROP_NAME_TRANSITION_HEIGHT);
            int endHeight = (int) endValues.values.get(PROP_NAME_TRANSITION_HEIGHT);
            //若發生變化,則建立屬性動畫對應的Animator
            if (startHeight != endHeight) {
                return ObjectAnimator
                        .ofFloat(endValues.view, "rotation", 0, 360)
                        .setDuration(2000);
            }

            return null;
        }
    }

定義好後,就可以像系統內建的Transition那樣,使用RotateWhenHeightChangeTransition了:

.......
//更改一下scene2對應的View的高度
//可以發現高度變化的View才會有旋轉動畫
Scene scene2 = Scene.getSceneForLayout(rootView,
        R.layout.scene2, MainActivity.this);
TransitionManager.go(scene2, new RotateWhenHeightChangeTransition());
........

四、總結
至此,我們已經明白過渡動畫的使用和自定義,
應該可以滿足一般的工作需求。

相關推薦

Android過渡動畫Transition Animation

本篇部落格記錄一下Android中過渡動畫的用法。 過渡動畫是Android 4.4引入的新的動畫框架,它本質上仍是屬性動畫, 但對屬性動畫做了一層封裝,以方便開發者實現Activity或者View的過渡動畫效果。 和屬性動畫相比,過渡動畫最大的不同是需要

Android 屬性動畫Property Animation 全然解析

顏色 valid 全部 加速度 ext target ng- 點擊 save 轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/380674751、概述Android提供了幾種動畫類型:View Anima

Android 屬性動畫Property Animation 完全解析 【轉】

轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/38067475 1、概述 Android提供了幾種動畫型別:View Animation 、Drawable Animation 、Property Anima

Android 屬性動畫Property Animation 完全解析

目錄(?)[+] 1、概述 Android提供了幾種動畫型別:View Animation 、Drawable Animation 、Property Animation 。View Animation相當簡單,不過只能支援簡單的縮放、平移、旋轉、透明度基本的動畫,

Android動畫Frame Animation 動畫停止在第一幀

專案中遇到的問題: 需求: 做一個聊天頁面,要求播放語音時,有一個類似於喇叭的動畫,從小到大不停迴圈,語音播放完,動畫停止在第一幀。當點選正在播放的語音時,語音停止,動畫回覆到第一幀(回覆到第一幀是難點) 實現:用Frame Animation   可以在Java程式碼中新

Android 屬性動畫Property Animation

1、概述 Android提供了幾種動畫型別:View Animation 、Drawable Animation 、Property Animation 。View Animation相當簡單,不過只能支援簡單的縮放、平移、旋轉、透明度基本的動畫,且有一定的侷限

vue——32-動畫-列表動畫transition-group

css li { border: 1px dashed red; margin: 5px; line-height: 35px; list-style: none;

屬性動畫property animation &重複執行

Android中的動畫分為檢視動畫(View Animation)即Tween Animation(補間動畫)、屬性動畫(Property Animation)以及Drawable動畫即Frame Animation(幀動畫)。從Android 3.0(API

iOS動畫Core Animation使用

#import <Foundation/Foundation.h> @interface AnimationManager : NSObject /* 閃爍動畫 * time:閃爍間隔 * repeatCount = MAXFLOAT(永久閃爍)重複次數 */ + (CABasic

iOS動畫Core Animation總結

一、簡介 iOS動畫主要是指Core Animation框架。官方使用文件地址為:Core Animation Guide。Core Animation是iOS和macOS平臺上負責圖形渲染與動畫的基礎框架。Core Animation可以作用與動畫檢視或者其他可視元素,

場景過渡動畫Scene Transition-簡單使用

1.先說一下 過渡動畫(Transition Animation)過度動畫有3種:場景過渡動畫(Scene Transition),Activity過渡動畫,共享元素過渡動畫(Shared Element Transition)這一次介紹Scene Transition的簡單

Android View動畫 --- scale

for -- 縮放 記錄 1.0 使用 tco 關於 mod 在我們做apk開發的過程中,如果要吸引用戶,就需要要做出來一個非常炫的界面,當然動畫是必不可少的,接下來就記錄和學習動畫相關…… 接下來就把平時的一些東西,慢慢的上傳上來,做一下記錄和保存 今天要講解的第一個

android動畫 插值器

插值器 首先要了解為什麼需要插值器,因為在補間動畫中,我們一般只定義關鍵幀(首幀或尾幀),然後由系統自動生成中間幀,生成中間幀的這個過程可以成為“插值”。插值器定義了動畫變化的速率,提供不同的函式定義變化值相對於時間的變化規則,可以定義各種各樣的非線性變化函式,比如加速、減速等。下面是幾種常

Android】屬性動畫基本用法

1、前言 在我們體驗一款APP時,炫酷的動畫往往能讓使用者體驗大幅度提升。想當年我剛學Android的時候,無意中看到蘑菇街購物車的動畫效果,把我給激動得,非要在自己的APP中加入那動畫,記得當時用費了好大的勁...不提了,說多了都是淚... 先了解下,目前可以實現動畫的

Android今日頭條微頭條點贊動畫

前言 設計很開心,又找到一個好看的效果。 開發很痛苦,又要百度找效果。納尼!!!沒找到!!! o(TωT)o 設計直接把原效果給我看,讓我抄… 預覽 APK下載 思路

載入RecycleView時為itemView新增一些過渡動畫

效果圖如下: 採用什麼方式實現該種動畫效果?   Android動畫可以分為三類:幀動畫(Frame Animation)、補間動畫(Tween Animation)、屬性動畫(Property Animation)。我們主要這裡用到了補

android字型閃爍動畫執行緒

android字型閃爍動畫,使用執行緒和Timer實現 public class ActivityMain extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCre

Android屬性動畫 TimeInterpolator插值器

OK,繼續學習屬性動畫,本篇文章是屬性動畫系列的第三篇文章了,今天來學習一下屬性動畫中的TimeInterpolator,如果你對屬性動畫還不太熟悉,可以點選下面的連結學習一下前兩篇文章的知識: 1.介紹 先說說Interpolator,在And

android 屬性動畫view普通使用 和 自定義view使用

1、概述 普通的動畫主要是Animation 和   Animator(與5.0的切換動畫,介面共享元素動畫區分開)  Animation 分 TranslateAnimation 移動 scaleAnimation 縮放 RotateAnimation 旋轉 AlphaA

前端框架Vue14—— 利用 vue 過渡效果transition+定時器 實現輪播圖通用元件

序論: 輪播圖 相信都不會陌生,很多的網站都會有,而且實現的方式也是千變萬化,可以利用封裝好的 UI 庫 (bootstrap), 也可以原生的 JS 進行編寫。但是其中,動畫(transition)和定時器都是必不可少的。本文就是利用 vue