如果本文幫助到你啊片,本人不勝榮幸,如果浪費(fèi)了你的時間玖像,本人深感抱歉紫谷。
希望用最簡單的大白話來幫助那些像我一樣的人。如果有什么錯誤捐寥,請一定指出笤昨,以免誤導(dǎo)大家、也誤導(dǎo)我握恳。
本文來自:http://www.reibang.com/users/320f9e8f7fc9/latest_articles
感謝您的關(guān)注瞒窒。
本文原項(xiàng)目地址為:
https://github.com/lgvalle/Material-Animations
在文章最后,有我自己對著這個項(xiàng)目手敲的一份乡洼。
代碼基本一模一樣崇裁,只有略微的修改,加了一些注釋束昵,以及將其中大多數(shù)英文翻譯成了中文拔稳。
此篇 API 均為 Android 5.0(API 級別 21) 以上才可支持。
此demo一共分為四部分:
1.1 普通過渡 Transition锹雏;
1.2 Shared Elements Transition 共享元素巴比;
2.0 TransitionManager 控制動畫;
3.0 ViewAnimationUtils 顯示或隱藏效果礁遵。
過渡效果 Transition
Material Design 為應(yīng)用中的切換頁面時匿辩,提供了非常優(yōu)雅的視覺切換效果。
您可為進(jìn)入榛丢、退出轉(zhuǎn)換、頁面之間的共享元素轉(zhuǎn)換設(shè)置特定的動畫挺庞。
1. Transition 動畫都包含哪些晰赞?
Android 5.0(API 級別 21)支持的進(jìn)入與退出轉(zhuǎn)換有三個:
Explode | Slide | Fade |
---|---|---|
從中心移入或移出 | 從邊緣移入或移出 | 調(diào)整透明度產(chǎn)生漸變 |
一會看到使用場景的時候,就會發(fā)現(xiàn)上面的三張圖,每張圖都經(jīng)歷了:(此處可以一會再回過頭來看)
退出 -> 進(jìn)入 -> 返回 -> 重新進(jìn)入
Exit -> Enter -> Return -> Reenter
**第一個頁面設(shè)置:**
android:windowExitTransition 啟動新 Activity 掖鱼,此頁面退出的動畫
android:windowReenterTransition 重新進(jìn)入的動畫然走。即第二次進(jìn)入,可以和首次進(jìn)入不一樣戏挡。
**第二個頁面設(shè)置:**
android:windowEnterTransition 首次進(jìn)入顯示的動畫
android:windowReturnTransition 調(diào)用 finishAfterTransition() 退出時芍瑞,此頁面退出的動畫
如此即可達(dá)到以上效果。
explode:從場景的中心移入或移出
slide:從場景的邊緣移入或移出
fade:調(diào)整透明度產(chǎn)生漸變效果
這三個類都繼承于 Transition 褐墅,所有有一些屬性都是共同的拆檬。
常用屬性如下:
// 設(shè)置動畫的時間。類型:long
transition.setDuration();
// 設(shè)置修飾動畫妥凳,定義動畫的變化率竟贯,具體設(shè)置往下翻就看到了
transition.setInterpolator();
// 設(shè)置動畫開始時間,延遲n毫秒播放逝钥。類型:long
transition.setStartDelay();
// 設(shè)置動畫的運(yùn)行路徑
transition.setPathMotion();
// 改變動畫 出現(xiàn)/消失 的模式屑那。Visibility.MODE_IN:進(jìn)入;Visibility.MODE_OUT:退出艘款。
transition.setMode();
// 設(shè)置動畫的監(jiān)聽事件
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 在動畫開始與結(jié)束的地方速率改變比較慢岳枷,在中間的時候加速
AccelerateInterpolator 在動畫開始的地方速率改變比較慢芒填,然后開始加速
AnticipateInterpolator 開始的時候向后然后向前甩
AnticipateOvershootInterpolator 開始的時候向后然后向前甩一定值后返回最后的值
BounceInterpolator 動畫結(jié)束的時候彈起
CycleInterpolator 動畫循環(huán)播放特定的次數(shù),速率改變沿著正弦曲線
DecelerateInterpolator 在動畫開始的地方快然后慢
LinearInterpolator 以常量速率改變
OvershootInterpolator 向前甩一定值后再回到原來位置
3. 設(shè)置 Transition 的時機(jī)
到底該什么時候空繁,設(shè)置什么樣的過渡呢殿衰?
以下為動畫的設(shè)置場景:
首先打開頁面A :
頁面A -> Enter 首次進(jìn)入
從 A 打開 B :
頁面A -> Exit 退出
頁面B -> Enter 首次進(jìn)入
從 B 返回 A :
頁面B -> Return 返回
頁面A -> Reenter 重新進(jìn)入
可設(shè)置的方法如下:
android:windowContentTransitions 允許使用transitions
android:windowAllowEnterTransitionOverlap 是否覆蓋執(zhí)行,其實(shí)可以理解成前后兩個頁面是同步執(zhí)行還是順序執(zhí)行
android:windowAllowReturnTransitionOverlap 與上面相同盛泡。即上一個設(shè)置了退出動畫闷祥,這個設(shè)置了進(jìn)入動畫,兩者是否同時執(zhí)行傲诵。
android:windowContentTransitionManager 引用TransitionManager XML資源凯砍,定義不同窗口內(nèi)容之間的所需轉(zhuǎn)換。
android:windowEnterTransition 首次進(jìn)入顯示的動畫
android:windowExitTransition 啟動新 Activity 拴竹,此頁面退出的動畫
android:windowReenterTransition 重新進(jìn)入的動畫悟衩。即第二次進(jìn)入,可以和首次進(jìn)入不一樣栓拜。
android:windowReturnTransition 調(diào)用 finishAfterTransition() 退出時座泳,此頁面退出的動畫
android:windowSharedElementsUseOverlay 指示共享元素在轉(zhuǎn)換期間是否應(yīng)使用疊加層惠昔。
android:windowSharedElementEnterTransition 首次進(jìn)入顯示的動畫
android:windowSharedElementExitTransition 啟動新 Activity ,此頁面退出的動畫
android:windowSharedElementReenterTransition 重新進(jìn)入的動畫挑势。即第二次進(jìn)入镇防,可以和首次進(jìn)入不一樣。
android:windowSharedElementReturnTransition 調(diào)用 finishAfterTransition() 退出時潮饱,此頁面退出的動畫
以上為 style 中設(shè)置屬性来氧,在代碼中設(shè)置為:
getWindow().setEnterTransition(visibility);
// 其余的都是類似
4. 跳轉(zhuǎn)頁面
至此,用以上知識基本可以設(shè)置出絕大多數(shù)的過渡效果香拉。
然后啦扬,跳轉(zhuǎn)頁面跟普通的跳轉(zhuǎn)也有點(diǎn)不一樣。
跳轉(zhuǎn)頁面:
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 被定義考传,將使用 反進(jìn)入 的動畫
finishAfterTransition();
}
注意:退出時,一定要調(diào)用:finishAfterTransition();
通過以上設(shè)置证鸥,就能夠完成一個基本的過渡效果了僚楞。
Shared Elements Transition 共享元素
效果如圖:
共享元素的各種設(shè)置 與 普通Transition 差不多。
來說說不同的地方枉层。
攜帶需要共享的 View 進(jìn)行跳轉(zhuǎn)
也就是在跳轉(zhuǎn)的參數(shù)中泉褐,增加了要共享的 View控件。
- 先在 layout 布局里面給需要共享的元素加上如下字段鸟蜡,這樣兩個 View 就能互通了:
android:transitionName="image"
- 然后開始設(shè)置跳轉(zhuǎn)頁面膜赃,代碼如下:
protected void transitionTo(Intent i) {
// 這里攜帶了兩個 View
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
Pair.create(view1, "agreedName1"),
Pair.create(view2, "agreedName2"));
startActivity(i, options.toBundle());
}
增加的參數(shù)的介紹:
Pair.create(
View view, // 本頁面要共享的 View
String resId // 下一個頁面的 View 的 id,注意是 id 的字符串
)
頁面切換時,動畫的效果設(shè)置
Android 5.0(API 級別 21)支持轉(zhuǎn)換效果如下:
changeBounds - 改變目標(biāo)視圖的布局邊界
changeClipBounds - 裁剪目標(biāo)視圖邊界
changeTransform - 改變目標(biāo)視圖的縮放比例和旋轉(zhuǎn)角度
changeImageTransform - 改變目標(biāo)圖片的大小和縮放比例
設(shè)置代碼:
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 控制動畫
這個框架可以讓一些復(fù)雜的動畫特別簡單的被實(shí)現(xiàn)。
簡單的說明一下步驟:
- 定義需要切換 layout xml頁面泣矛;
- 調(diào)用 Scene.getSceneForLayout() 保存每個Layout疲眷;
- 調(diào)用 TransitionManager.go(scene1, new ChangeBounds()) 切換。
相當(dāng)于定義了不同的 xml 布局您朽,然后通過簡單的調(diào)用狂丝,就完成了較為復(fù)雜的動畫。
以下為代碼片段:
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;
}
}
只需要定義布局哗总,調(diào)用調(diào)轉(zhuǎn)几颜,
就實(shí)現(xiàn)了,點(diǎn)擊四個 Button 讯屈,分別切換四個布局蛋哭。
TransitionManager.go() 中可以設(shè)置各種動畫。
CircularReveal 顯示或隱藏 的效果
ViewAnimationUtils.createCircularReveal()
當(dāng)您顯示或隱藏一組 UI 元素時涮母,Circular Reveal 可為用戶提供視覺連續(xù)性
參數(shù)說明:
Animator createCircularReveal (View view, // 將要變化的 View
int centerX, // 動畫圓的中心的x坐標(biāo)
int centerY, // 動畫圓的中心的y坐標(biāo)
float startRadius, // 動畫圓的起始半徑
float endRadius // 動畫圓的結(jié)束半徑
)
顯示 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());
//為此視圖創(chuàng)建動畫設(shè)計(起始半徑為零)
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();
}
因?yàn)榫咦常@些炫酷的效果都只支持 API 23 以上准颓,所以在我們常用的 APP 中都還不常見。但是效果真的很不錯棺妓。
值得大家研究一下。
此文是我的一個總結(jié)炮赦。
項(xiàng)目地址:
https://github.com/Wing-Li/Material-Animations-CN
這個項(xiàng)目是我對著原項(xiàng)目手敲的怜跑,
基本一模一樣,只是加了一些注釋吠勘,以及將其中英文翻譯成了中文性芬。
大家可以參考參考。