Transition:Activity過渡、共享元素動畫
本文原專案地址為:
https://github.com/lgvalle/Material-Animations
在文章最後,有我自己對著這個專案手敲的一份。
程式碼基本一模一樣,只有略微的修改,加了一些註釋,以及將其中大多數英文翻譯成了中文。
此篇 API 均為 Android 5.0(API 級別 21) 以上才可支援。
此demo一共分為四部分:
1.1 普通過渡 Transition;
1.2 Shared Elements Transition 共享元素;
2.0 TransitionManager 控制動畫;
3.0 ViewAnimationUtils 顯示或隱藏效果。
過渡效果 Transition
Material Design 為應用中的切換頁面時,提供了非常優雅的視覺切換效果。
您可為進入、退出轉換、頁面之間的共享元素轉換設定特定的動畫。
1. Transition 動畫都包含哪些?
Android 5.0(API 級別 21)支援的進入與退出轉換有三個:
Explode | Slide | Fade |
---|---|---|
從中心移入或移出 | 從邊緣移入或移出 | 調整透明度產生漸變 |
一會看到使用場景的時候,就會發現上面的三張圖,每張圖都經歷了:(此處可以一會再回過頭來看)
退出 -> 進入 -> 返回 -> 重新進入 Exit -> Enter -> Return -> Reenter **第一個頁面設定:** android:windowExitTransition 啟動新 Activity ,此頁面退出的動畫 android:windowReenterTransition 重新進入的動畫。即第二次進入,可以和首次進入不一樣。 **第二個頁面設定:** android:windowEnterTransition 首次進入顯示的動畫 android:windowReturnTransition 呼叫 finishAfterTransition() 退出時,此頁面退出的動畫 如此即可達到以上效果。
explode:從場景的中心移入或移出
slide:從場景的邊緣移入或移出
fade:調整透明度產生漸變效果
這三個類都繼承於 Transition ,所有有一些屬性都是共同的。
常用屬性如下:
// 設定動畫的時間。型別:long
transition.setDuration();
// 設定修飾動畫,定義動畫的變化率,具體設定往下翻就看到了
transition.setInterpolator();
// 設定動畫開始時間,延遲n毫秒播放。型別:long
transition.setStartDelay();
// 設定動畫的執行路徑
transition.setPathMotion();
// 改變動畫 出現/消失 的模式。Visibility.MODE_IN:進入;Visibility.MODE_OUT:退出。
transition.setMode();
// 設定動畫的監聽事件
transition.addListener()
至於例子,在下一個給出。
喏,這不就是了。
2. 修飾動畫,定義動畫的變化率(Interpolator)
在 Java 程式碼中定義:
Explode transition = new Explode();
transition.setDuration(500);
transition.setInterpolator(new AccelerateInterpolator());
在 Xml 資源定義:
<explode
android:duration="@integer/anim_duration_long"
android:interpolator="@android:interpolator/bounce"
/>
可選型別:
AccelerateDecelerateInterpolator 在動畫開始與結束的地方速率改變比較慢,在中間的時候加速
AccelerateInterpolator 在動畫開始的地方速率改變比較慢,然後開始加速
AnticipateInterpolator 開始的時候向後然後向前甩
AnticipateOvershootInterpolator 開始的時候向後然後向前甩一定值後返回最後的值
BounceInterpolator 動畫結束的時候彈起
CycleInterpolator 動畫迴圈播放特定的次數,速率改變沿著正弦曲線
DecelerateInterpolator 在動畫開始的地方快然後慢
LinearInterpolator 以常量速率改變
OvershootInterpolator 向前甩一定值後再回到原來位置
3. 設定 Transition 的時機
到底該什麼時候,設定什麼樣的過渡呢?
以下為動畫的設定場景:
首先開啟頁面A :
頁面A -> Enter 首次進入
從 A 開啟 B :
頁面A -> Exit 退出
頁面B -> Enter 首次進入
從 B 返回 A :
頁面B -> Return 返回
頁面A -> Reenter 重新進入
可設定的方法如下:
android:windowContentTransitions 允許使用transitions
android:windowAllowEnterTransitionOverlap 是否覆蓋執行,其實可以理解成前後兩個頁面是同步執行還是順序執行
android:windowAllowReturnTransitionOverlap 與上面相同。即上一個設定了退出動畫,這個設定了進入動畫,兩者是否同時執行。
android:windowContentTransitionManager 引用TransitionManager XML資源,定義不同視窗內容之間的所需轉換。
android:windowEnterTransition 首次進入顯示的動畫
android:windowExitTransition 啟動新 Activity ,此頁面退出的動畫
android:windowReenterTransition 重新進入的動畫。即第二次進入,可以和首次進入不一樣。
android:windowReturnTransition 呼叫 finishAfterTransition() 退出時,此頁面退出的動畫
android:windowSharedElementsUseOverlay 指示共享元素在轉換期間是否應使用疊加層。
android:windowSharedElementEnterTransition 首次進入顯示的動畫
android:windowSharedElementExitTransition 啟動新 Activity ,此頁面退出的動畫
android:windowSharedElementReenterTransition 重新進入的動畫。即第二次進入,可以和首次進入不一樣。
android:windowSharedElementReturnTransition 呼叫 finishAfterTransition() 退出時,此頁面退出的動畫
以上為 style 中設定屬性,在程式碼中設定為:
getWindow().setEnterTransition(visibility);
// 其餘的都是類似
4. 跳轉頁面
至此,用以上知識基本可以設定出絕大多數的過渡效果。
然後,跳轉頁面跟普通的跳轉也有點不一樣。
跳轉頁面:
protected void transitionTo(Intent i) {
ActivityOptionsCompat transitionActivityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(this);
startActivity(i, transitionActivityOptions.toBundle());
}
退出頁面:
private void closeActivity(){
// 如果定義了 return transition ,將使用 定義的動畫過渡
Visibility returnTransition = buildReturnTransition();
getWindow().setReturnTransition(returnTransition);
// 如果沒有 return transition 被定義,將使用 反進入 的動畫
finishAfterTransition();
}
注意:退出時,一定要呼叫:finishAfterTransition();
通過以上設定,就能夠完成一個基本的過渡效果了。
Shared Elements Transition 共享元素
效果如圖:
Shared Elements Transition
共享元素的各種設定 與 普通Transition 差不多。
來說說不同的地方。
攜帶需要共享的 View 進行跳轉
也就是在跳轉的引數中,增加了要共享的 View控制元件。
程式碼如下:
protected void transitionTo(Intent i) {
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
Pair.create(view1, "agreedName1"),
Pair.create(view2, "agreedName2"));
startActivity(i, options.toBundle());
}
增加的引數的介紹:
Pair.create(
View view, // 本頁面要共享的 View
String resId // 下一個頁面的 View 的 id,注意是 id 的字串
)
頁面切換時,動畫的效果設定
Android 5.0(API 級別 21)支援轉換效果如下:
changeBounds - 改變目標檢視的佈局邊界
changeClipBounds - 裁剪目標檢視邊界
changeTransform - 改變目標檢視的縮放比例和旋轉角度
changeImageTransform - 改變目標圖片的大小和縮放比例
設定程式碼:
Slide slide = new Slide();
slide.setDuration(500);
ChangeBounds changeBounds = new ChangeBounds();
changeBounds.setDuration(500);
getWindow().setEnterTransition(slide);
getWindow().setSharedElementEnterTransition(changeBounds);
Shared Elements Transition 就是 特殊的 Transition 用法,都是一樣的。
TransitionManager 控制動畫
這個框架可以讓一些複雜的動畫特別簡單的被實現。
TransitionManager
簡單的說明一下步驟:
- 定義需要切換 layout xml頁面;
- 呼叫 Scene.getSceneForLayout() 儲存每個Layout;
- 呼叫 TransitionManager.go(scene1, new ChangeBounds()) 切換。
相當於定義了不同的 xml 佈局,然後通過簡單的呼叫,就完成了較為複雜的動畫。
以下為程式碼片段:
private void setupLayout() {
scene0 = Scene.getSceneForLayout(binding.sceneRoot, R.layout.activity_animations_scene0, this);
scene1 = Scene.getSceneForLayout(binding.sceneRoot, R.layout.activity_animations_scene1, this);
scene2 = Scene.getSceneForLayout(binding.sceneRoot, R.layout.activity_animations_scene2, this);
scene3 = Scene.getSceneForLayout(binding.sceneRoot, R.layout.activity_animations_scene3, this);
scene4 = Scene.getSceneForLayout(binding.sceneRoot, R.layout.activity_animations_scene4, this);
binding.sample3Button1.setOnClickListener(this);
binding.sample3Button2.setOnClickListener(this);
binding.sample3Button3.setOnClickListener(this);
binding.sample3Button4.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.sample3_button1:
TransitionManager.go(scene1, new ChangeBounds());
break;
case R.id.sample3_button2:
TransitionManager.go(scene2, TransitionInflater.from(this).inflateTransition(R.transition.slide_and_changebounds));
break;
case R.id.sample3_button3:
TransitionManager.go(scene3,TransitionInflater.from(this).inflateTransition(R.transition.slide_and_changebounds_sequential));
break;
case R.id.sample3_button4:
TransitionManager.go(scene3,TransitionInflater.from(this).inflateTransition(R.transition.slide_and_changebounds_sequential_with_interpolators));
break;
}
}
只需要定義佈局,呼叫調轉,
就實現了,點選四個 Button ,分別切換四個佈局。
TransitionManager.go() 中可以設定各種動畫。
CircularReveal 顯示或隱藏 的效果
ViewAnimationUtils.createCircularReveal()
當您顯示或隱藏一組 UI 元素時,Circular Reveal 可為使用者提供視覺連續性
CircularReveal
引數說明:
Animator createCircularReveal (View view, // 將要變化的 View
int centerX, // 動畫圓的中心的x座標
int centerY, // 動畫圓的中心的y座標
float startRadius, // 動畫圓的起始半徑
float endRadius // 動畫圓的結束半徑
)
顯示 View :
private void animShow() {
View myView = findViewById(R.id.my_view);
// 從 View 的中心開始
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
//為此檢視建立動畫設計(起始半徑為零)
Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
// 使檢視可見並啟動動畫
myView.setVisibility(View.VISIBLE);
anim.start();
}
隱藏 View :
private void animHide() {
final View myView = findViewById(R.id.my_view);
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
int initialRadius = myView.getWidth();
// 半徑 從 viewWidth -> 0
Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
});
anim.start();
}
因為,這些炫酷的效果都只支援 API 23 以上,所以在我們常用的 APP 中都還不常見。但是效果真的很不錯。
值得大家研究一下。
此文是我的一個總結。
專案地址:
https://github.com/Wing-Li/Material-Animations-CN
這個專案是我對著原專案手敲的,
基本一模一樣,只是加了一些註釋,以及將其中英文翻譯成了中文。
大家可以參考參考。
文/Wing_Li(簡書作者)
原文連結:http://www.jianshu.com/p/a43daa1e3d6e
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。