安卓過渡動(dòng)畫入門介紹

Android

轉(zhuǎn)自 泡在網(wǎng)上的日子
英文原文 https://github.com/lgvalle/Material-Animations

  • 安卓的Transition框架主要運(yùn)用在以下三種情況:

    1.activity之間或者Fragment之間的過渡動(dòng)畫。

    2.activity之間或者Fragment之間的共享元素(又叫hero view)的過渡動(dòng)畫。

    3.activity中布局元素的過渡動(dòng)畫。

其實(shí)1和2都是用于activity(或者)切換的時(shí)候。而且1和2是可以同時(shí)使用的。
ps :雖然overridePendingTransition也可以實(shí)現(xiàn)activity的切換,但是overridePendingTransition 沒有共享元素的切換效果。而第三種其實(shí)是最簡(jiǎn)單的,主要調(diào)用幾個(gè)已經(jīng)定義好的動(dòng)畫類就可以了。

    1. activity之間的過度動(dòng)畫

activity之間的過度動(dòng)畫

可以在xml中定義這種動(dòng)畫
res/transition/activity_explode.xml

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <explode android:duration="2000"/>
</transitionSet>

res/values/style.xml

<item name="android:windowEnterTransition">@transition/activity_explode.xml</item>

也可以通過代碼的方式:
MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    setupWindowAnimations();
}
 
private void setupWindowAnimations() {
    Explode explode = new Explode();
    explode.setDuration(2000);
    getWindow().setExitTransition(explode);
}

DetailActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    setupWindowAnimations();
}
 
private void setupWindowAnimations() {
    Explode explode = new Explode();
    explode.setDuration(2000);
    getWindow().setEnterTransition(explode);
}
示意圖
  • 一步步解釋上面的過程:
    1.Activity A調(diào)用Activity B

    2.Transition框架發(fā)現(xiàn)A的Exit Transition(這里是explode效果的過渡動(dòng)畫)將其應(yīng)用到所有的可見view。

    3.Transition框架發(fā)現(xiàn)B的Enter Transition (explode),將其應(yīng)用到所有的可見view。

    4.點(diǎn)擊返回的時(shí)候Transition 框架分別執(zhí)行各自Enter與Exit的反向動(dòng)畫(因?yàn)樗鼪]有找到returnTransition和reenterTransition)。

ReturnTransition & ReenterTransition
這兩個(gè)方法定義A的exit動(dòng)畫和B的enter動(dòng)畫的相反方向的動(dòng)畫,即A的進(jìn)入與B的離開。我們就成為返回動(dòng)畫吧。

Paste_Image.png

在本例中,我們這樣:
MainActivity.java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setupWindowAnimations();
    }
 
    private void setupWindowAnimations() {
        Explode explode = new Explode();
        explode.setDuration(2000);
        getWindow().setExitTransition(explode);
 
        Fade fade = new Fade();
        fade.setDuration(2000);
        getWindow().setReenterTransition(fade);
 
    }

DetailActivity.java

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setupWindowAnimations();
    }
 
    private void setupWindowAnimations() {
        Explode explode = new Explode();
        expl.setDuration(2000);
        getWindow().setEnterTransition(explode);
 
        Fade fade = new Fade();
        fade.setDuration(2000);
        getWindow().setReturnTransition(fade);        
    }

Paste_Image.png

2.Activity間的共享元素
共 享元素過度動(dòng)畫的背后是通過過度動(dòng)畫將兩個(gè)不同布局中的不同view關(guān)聯(lián)起來。Transition框架知道用適當(dāng)?shù)膭?dòng)畫向用戶展示從一個(gè)view向另外 一個(gè)view過度。請(qǐng)記?。汗蚕碓剡^度的過程中,view并沒有真正從一個(gè)布局跑到另外一個(gè)布局,整個(gè)過程基本都是在后一個(gè)布局中完成的。

Paste_Image.png

可以看到,這里有兩個(gè)id分別為smallSquare和bigSquare的view,但是他們有相同的transitionName。這樣Transition就知道此時(shí)需要?jiǎng)?chuàng)建一個(gè)從一個(gè)view到另外一個(gè)view的動(dòng)畫。
MainActivity.java

squareBlue.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent i = new Intent(MainActivity.this, DetailActivity2.class);
 
        View sharedView = squareBlue;
        String transitionName = getString(R.string.square_blue_name);
 
        ActivityOptions transitionActivityOptions = ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, sharedView, transitionName);
        startActivity(i, transitionActivityOptions.toBundle());
    }
});

layout/main_activity.xml

<View
        android:layout_margin="10dp"
        android:id="@+id/square_blue"
        android:layout_width="50dp"
        android:background="@android:color/holo_blue_light"
        android:transitionName="@string/square_blue_name"
        android:layout_height="50dp"/>

layou/details_activity2.xml

<View
        android:layout_width="150dp"
        android:id="@+id/big_square_blue"
        android:layout_margin="10dp"
        android:transitionName="@string/square_blue_name"
        android:layout_centerInParent="true"
        android:background="@android:color/holo_blue_light"
        android:layout_height="150dp" />
Paste_Image.png

可以看到Transition框架創(chuàng)建了一個(gè)讓你感覺view在移動(dòng)與變大的動(dòng)畫效果。

為了證明blue square這個(gè)view并沒有真正移動(dòng),我們可以做一個(gè)這樣的實(shí)現(xiàn):將transitioName賦予Big Blue Square上面的TextView。

<TextView
        android:layout_width="wrap_content"
        android:text="Activity Detail 2"
        style="@style/Base.TextAppearance.AppCompat.Large"
        android:layout_centerHorizontal="true"
        android:transitionName="@string/square_blue_name"
        android:layout_above="@+id/big_square_blue"
        android:layout_height="wrap_content" />

運(yùn)行之后你可以看到這次有相同的行為,但是作用在了一個(gè)不同的view上:

Paste_Image.png

3. 布局元素的過渡動(dòng)畫
Transition框架還可以用于activity布局中view從一種狀態(tài)到另一種狀態(tài)的過渡動(dòng)畫。
如果你想知道關(guān)于過渡動(dòng)畫的更多知識(shí),請(qǐng)觀看這個(gè)視頻this video by Chet Hasse。
本文盡量采用簡(jiǎn)單的例子

TransitionManager.beginDelayedTransition(sceneRoot);

這行代碼告訴framework,我們將要做一些UI上的變化,這些變化需要相應(yīng)的動(dòng)畫效果。
對(duì)UI元素進(jìn)行變更:

setViewWidth(squareRed, 500);
setViewWidth(squareBlue, 500);
setViewWidth(squareGreen, 500);
setViewWidth(squareYellow, 500);

這會(huì)改變相應(yīng)view的屬性,讓其變大。Transition框架將記錄開始和結(jié)束的的值,然后創(chuàng)建一個(gè)過渡動(dòng)畫。

 squareGreen.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                TransitionManager.beginDelayedTransition(sceneRoot);
                setViewWidth(squareRed, 500);
                setViewWidth(squareBlue, 500);
                setViewWidth(squareGreen, 500);
                setViewWidth(squareYellow, 500);
            }
        });
    }
 
    private void setViewWidth(View view, int x) {
        ViewGroup.LayoutParams params = view.getLayoutParams();
        params.width = x;
        view.setLayoutParams(params);
    }
Paste_Image.png

相關(guān)資料

lex Lockwood發(fā)表了幾篇關(guān)于Lollipop的transition的幾篇文章,非常深入的討論了這個(gè)話題http://www.androiddesignpatterns.com/2014/12/activity-fragment-transitions-in-android-lollipop-part1.html 中文地址 http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0113/2310.html

Saul Molinero關(guān)于transition的比較完善的示例項(xiàng)目:https://github.com/saulmm/Android-Material-Examples
Chet Hasse解釋Transition framework的視頻: https://www.youtube.com/watch?v=S3H7nJ4QaD8

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容