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)畫類就可以了。
- 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 B2.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)畫吧。

在本例中,我們這樣:
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);
}

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è)布局中完成的。

可以看到,這里有兩個(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" />

可以看到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上:

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);
}

相關(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